Regex for UK postcode - regex

I have this regex that I want to use to parse a UK postcode, but it doesn't work when a postcode is entered without spaces.
^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]?) {1,2}([0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$
What change(s) do I need to make to this regex so it'll work without spaces correctly?
If I supply LS28NG I would expect the regex to return two matches for LS2 and 8NG.

This worked for me, at least for your example of LS28NG:
^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]?) {0,2}([0-9][ABD-HJLN-UW-Z]{2}|GIR ?0AA)$
I changed the repetitions after the space to 0-2 instead of 1-2, and made the space in GIR 0AA optional.

Try adding \s{0,2} and putting brackets around the first and second part of the expression:
^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]?)\s{0,2}([0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$
For:
LS2 8NG
LS28NG
It will match:
LS2 and 8NG
LS2 and 8NG
See it in action.

Just add an optional space \s? at the end of the first group:
^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]?\s?){1,2}([0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$

Related

Need regex help for matching names

Let's say I have these three names
John Doe (p45643)
Le'anne Frank
Molly-Mae Edwards
I want to match
1) John Doe
2) Le'anne Frank
3) Molly-Mae Edwards
The regex I have tried is
(^[a-zA-Z-'^\d]$)+
but it isn't working as I am expecting.
I would like help creating a regex pattern that:
Matches a name from start to finish, and cannot contain a number. The only permitted values each "name" can contain is, [a-zA-Z'-], so if a name was
J0hn then it shouldn't match
If I understood correctly your question, then you have a minor errors in your regex:
(^[a-zA-Z-'^\d]$)+
^-------^------Here
The - pointed above should be escaped or moved to the end since it works as a range character. The + is marking the group as repeated.
You can use this regex instead (following your previous pattern):
(^[a-zA-Z'^\d -]+$)
Regex demo
Update: for your comment. If you want to match separately, then you can use:
(\b[a-zA-Z'^\d-]+\b)
Regex demo
And if you only want to match string (not numbers), then you can use:
(\b[a-zA-Z'-]+\b)
Regex demo
You are using the anchors incorrectly. Based on the modifier it can match the whole string or a single line.
Try
/^[a-zA-Z'-]+$/
Thanks to #Djory Krache
The query I was looking for was
(\b[a-zA-Z'-]+\b)

Regex - Skip characters to match

I'm having an issue with Regex.
I'm trying to match T0000001 (2, 3 and so on).
However, some of the lines it searches has what I can describe as positioners. These are shown as a question mark, followed by 2 digits, such as ?21.
These positioners describe a new position if the document were to be printed off the website.
Example:
T123?214567
T?211234567
I need to disregard ?21 and match T1234567.
From what I can see, this is not possible.
I have looked everywhere and tried numerous attempts.
All we have to work off is the linked image. The creators cant even confirm the flavour of Regex it is - they believe its Python but I'm unsure.
Regex Image
Update
Unfortunately none of the codes below have worked so far. I thought to test each code in live (Rather than via regex thinking may work different but unfortunately still didn't work)
There is no replace feature, and as mentioned before I'm not sure if it is Python. Appreciate your help.
Do two regex operations
First do the regex replace to replace the positioners with an empty string.
(\?[0-9]{2})
Then do the regex match
T[0-9]{7}
If there's only one occurrence of the 'positioners' in each match, something like this should work: (T.*?)\?\d{2}(.*)
This can be tested here: https://regex101.com/r/XhQXkh/2
Basically, match two capture groups before and after the '?21' sequence. You'll need to concatenate these two matches.
At first, match the ?21 and repace it with a distinctive character, #, etc
\?21
Demo
and you may try this regex to find what you want
(T(?:\d{7}|[\#\d]{8}))\s
Demo,,, in which target string is captured to group 1 (or \1).
Finally, replace # with ?21 or something you like.
Python script may be like this
ss="""T123?214567
T?211234567
T1234567
T1234434?21
T5435433"""
rexpre= re.compile(r'\?21')
regx= re.compile(r'(T(?:\d{7}|[\#\d]{8}))\s')
for m in regx.findall(rexpre.sub('#',ss)):
print(m)
print()
for m in regx.findall(rexpre.sub('#',ss)):
print(re.sub('#',r'?21', m))
Output is
T123#4567
T#1234567
T1234567
T1234434#
T123?214567
T?211234567
T1234567
T1234434?21
If using a replace functionality is an option for you then this might be an approach to match T0000001 or T123?214567:
Capture a T followed by zero or more digits before the optional part in group 1 (T\d*)
Make the question mark followed by 2 digits part optional (?:\?\d{2})?
Capture one or more digits after in group 2 (\d+).
Then in the replacement you could use group1group2 \1\2.
Using word boundaries \b (Or use assertions for the start and the end of the line ^ $) this could look like:
\b(T\d*)(?:\?\d{2})?(\d+)\b
Example Python
Is the below what you want?
Use RegExReplace with multiline tag (m) and enable replace all occurrences!
Pattern = (T\d*)\?\d{2}(\d*)
replace = $1$2
Usage Example:

Non-greedy matching

In Geany, I want to match the titles of books. One example:
Michael Lewis, Liar's Poker, Hodder & Stoughton Ltd, London, 1989
I try to do so with this regex code:
,\s.*?,
This regex matches too much. it matches: [, Liar's Poker,] and [,London,].
I want to have a regex that only matches the title.
I think you need this regex with no global modifier. If you set global modifier i.e. g then it will return further matches like you have experienced.
,\s*([^,]+)
Demo
As you want to ignore further matches thus you may try this too:
^.*?,\s*([^,]+).*$
You will get Liar's Poker in group 1
Demo 2
/(, \w+[']?\w? \w+,)/g
this regex will get you this
[", Liar's Poker,"]
you will have to do additional processing to remove those leading and trailing commas. Try it out and see if this works for you.

Regular Expression to exclude numerical emailids

I have below set of sample emailids
EmailAddress
1123
123.123
123_123
123#123.123
123#123.com
123#abc.com
123mbc#abc.com
123mbc#123abc.com
123mbc#123abc.123com
123mbc123#cc123abc.c123com
Need to eliminate mailids if they contain entirely numericals before #
Expected output:
123mbc#abc.com
123mbc#123abc.com
123mbc#123abc.123com
123mbc123#cc123abc.c123com
I used below Java Rex. But its eliminating everything. I have basic knowledge in writing these expressions. Please help me in correcting below one. Thanks in advance.
[^0-9]*#.*
do you mean something like this ? (.*[a-zA-Z].*[#]\w*\.\w*)
breakdown .* = 0 or more characters [a-zA-Z] = one
letter .* = 0 or more characters #
\w*\.\w* endless times a-zA-Z0-9 with a single . in between
this way you have the emails that contains at least one letter
see the test at https://regex101.com/r/qV1bU4/3
edited as suggest by ccf with updated breakdown
The following regex only lets email adresses pass that meet your specs:
(?m)^.*[^0-9#\r\n].*#
Observe that you have to specify multi-line matching ( m flag. See the live demo. The solution employs the embedded flag syntax m flag. You can also call Pattern.compile with the Pattern.MULTILINE argument. ).
Live demo at regex101.
Explanation
Strategy: Define a basically sound email address as a single-line string containing a #, exclude strictly numerical prefixes.
^: start-of-line anchor
#: a basically sound email address must match the at-sign
[^...]: before the at sign, one character must neither be a digit nor a CR/LF. # is also included, the non-digit character tested for must not be the first at-sign !
.*: before and after the non-digit tested for, arbitrary strings are permitted ( well, actually they aren't, but true syntactic validation of the email address should probably not happen here and should definitely not be regex based for reasons of reliability and code maintainability ). The strings need to be represented in the pattern, because the pattern is anchored.
Try this one:
[^\d\s].*#.+
it will match emails that have at least one letter or symbol before the # sign.

TextMate: Regex replacing $1 with following 0

I'm trying to fix a file full of 1- and 2-digit numbers to make them all 2 digits long.
The file is of the form:
10,5,2
2,4,5
7,7,12
...
I've managed to match the problem numbers with:
(^|,)(\d)(,|$)
All I want to do now is replace the offending string with:
${1}0$2$3
but TextMate gives me:
10${1}05,2
Any ideas?
Thanks in advance,
Ross
According to this, TextMate supports word boundary anchors, so you could also search for \b\d\b and replace all with 0$0. (Thanks to Peter Boughton for the suggestion!)
This has the advantage of catching all the numbers in one go - your solution will have to be applied at least twice because the regex engine has already consumed the comma before the next number after a successful replace.
Note: Tim's solution is simpler and solves this problem, but I'll leave this here for reference, in case someone has a similar but more complex problem, which using lookarounds can support.
A simpler way than your expression is to replace:
(?<!\d)\d(?!\d)
With:
0$0
Which is "replace all single digits with 0 then itself".
The regex is:
Negative lookbehind to not find a digit (?<!\d)
A single digit: \d
Negative lookahead to not find a digit (?!\d)
Single this is a positional match (not a character match), it caters for both comma and start/end positions.
The $0 part says "entire match" - since the lookbehind/ahead match positions, this will contain the single digit that was matched.
To anyone coming here, as #Amarghosh suggested, it's a bug, or intentional behavior that leads to problems if nothing else.
I just had this problem and had to use the following workaround: If you set up another capture group, and then use a conditional insertion, it will work. For example, I had a string like <WebObject name=Frage01 and wanted to replace the 01 with 02, so I captured the main string in $1 and the end number in $2, which gave me a regex that looked like (<WebObject name=(Frage|Antwort))(01).
Then the replace was $1(?2:02).
The (?2:02) is the conditional insertion, and in this instance will always find something, but it was necessary in order to work around the odd conundrum of appending a number to the end of $n. Hope that helps someone. There is documentation on the conditional insertion here
In TextMate 1.5.11 (1635) ${1} does not work (like the OP described).
I appreciate the many suggestions re altering the query string, however there is a much simpler solution, if you want to break between a capture group and a number: \u.
It is a TextMate specific replacement syntax, that converts the following character to uppercase. As there is no uppercase for numbers, it does nothing and moves on. It is described in the link from Tim Pietzcker's answer.
In my case I had to clean up a csv file, where box measurements were given in cm x cm x mm. Thus I had to add a zero to the first two numbers.
Text: "80 x 40 x 5 mm"
Desired text: "800 x 400 x 5 mm"
Find: (\d+) x (\d+) x (\d+)
Replace: $1\u0 x $2\u0 x $3 mm
Regarding the support of more than 10 capture groups, I do not know if this is a bug. But as OP and #rossmcf wrote, $10 is replaced with null.
You need not ${1} - replace strings support only up to nine groups maximum - so it won't mistake it for $10.
Replace with $10$2$3