Having trouble creating a regex for a list of zip codes - regex

I need to test whether a list of zip codes in a textarea has only 5-digit zip codes. Under normal circumstances the list would look like this:
56228, 56243, 55324, 55325, 55329, 55355, 55389
I need to find out if there is anything but the above pattern in the textarea. There can be any number of individual zip codes, but I need to make sure there isn't anything else. (I think I'm going to need to be able to highlight illegal matches in the textarea also, but I'll cross that bridge when I get to it).
I started with this regex:
^\d{5},?\s?$+
I'm very new to building regular expressions, but as I understand it, the above should match any set of 5 digits, and commas and whitespace after the five digits may or may not be there.
Online regex testers (I've tried several) aren't finding any matches, whether I have a legitimate list of zip codes or a list with "illegal" characters.
What am I missing here?

This one should suit your needs:
^([, ]*\d{5})+[, ]*$

Related

Use regex in UFT PDF comparison

In one of my UFT test cases, I need to verify a amount on a PDF file.
Sometimes the amount is "3000" and sometimes it is "3.000". And sometimes even "3 000"!
I would like to accept those 3 possibilities, knowing that this amount is stored in a datatable.
I tried something like "3.?000" (with regex check in the file checkpoint) but it's not matching any of the 3 solutions.
How would you do?
One of UFT's idiosyncrasies when dealing with regexs is that it add implicit anchors at the beginning and ends of lines.
Try adding .* before and after the text you want to match - .*\s3[., ]?000\s.*.
Also verify that you've activated the regular expression flag for your line. I find the UI for File Content Checkpoints to be a bit unintuitive so you may have missed that.

Matching within matches by extending an existing Regex

I'm trying to see if its possible to extend an existing arbitrary regex by prepending or appending another regex to match within matches.
Take the following example:
The original regex is cat|car|bat so matching output is
cat
car
bat
I want to add to this regex and output only matches that start with 'ca',
cat
car
I specifically don't want to interpret a whole regex, which could be quite a long operation and then change its internal content to match produce the output as in:
^ca[tr]
or run the original regex and then the second one over the results. I'm taking the original regex as an argument in python but want to 'prefilter' the matches by adding the additional code.
This is probably a slight abuse of regex, but I'm still interested if it's possible. I have tried what I know of subgroups and the following examples but they're not giving me what I need.
Things I've tried:
^ca(cat|car|bat)
(?<=ca(cat|car|bat))
(?<=^ca(cat|car|bat))
It may not be possible but I'm interested in what any regex gurus think. I'm also interested if there is some way of doing this positionally if the length of the initial output is known.
A slightly more realistic example of the inital query might be [a-z]{4} but if I create (?<=^ca([a-z]{4})) it matches against 6 letter strings starting with ca, not 4 letter.
Thanks for any solutions and/or opinions on it.
EDIT: See solution including #Nick's contribution below. The tool I was testing this with (exrex) seems to have a slight bug that, following the examples given, would create matches 6 characters long.
You were not far off with what you tried, only you don't need a lookbehind, but rather a lookahead assertion, and a parenthesis was misplaced. The right thing is: Put the original pattern in parentheses, and prepend (?=ca):
(?=ca)(cat|car|bat)
(?=ca)([a-z]{4})
In the second example (without | alternative), the parentheses around the original pattern wouldn't be required.
Ok, thanks to #Armali I've come to the conclusion that (?=ca)(^[a-z]{4}$) works (see https://regexr.com/3f4vo). However, I'm trying this with the great exrex tool to attempt to produce matching strings, and it's producing matches that are 6 characters long rather than 4. This may be a limitation of exrex rather than the regex, which seems to work in other cases.
See #Nick's comment.
I've also raised an issue on the exrex GitHub for this.

Extract only the text field needed

I am at the beginning of learning Regex, and I use every opportunity to understand how it's working. Currently I am trying to extract dates from a text file (which is in fact a vnt-file type from my mobile phone). It looks like following:
BEGIN:VNOTE
VERSION:1.1
BODY;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:18.07.=0A14.08.=0A15.09.=0A15.10.=
=0A13.11.=0A13.12.=0A12.01.=0A03.02. Grippe=0A06.03.=0A04.04.2015=0A0=
5.05.2015=0A03.06.2015=0A03.07.2015=0A02.08.2015=0A30.08.2015=0A28.09=
17.11.2017=0A
DCREATED:20171118T095601
X-IRMC-LUID:150
END:VNOTE
I want to extract all dates, so that the final list is like that:
18.07.
14.08.
15.09.
15.10.
and so on. If the date has also a year, it should also be displayed.
I almost found out how to detect the dates by the following regex:
.+(\d\d\.\d\d\.(2015|2016|2017)?).+
But it only detect very few of the dates. The result is this:
BEGIN:VNOTE
VERSION:1.1
15.10.
04.04.2015
30.08.2015
24.01.2016
DCREATED:20171118T075601
X-IRMC-LUID:150
END:VNOTE
Then I tried to add a question mark which makes the .+ not greedy, as far as I read in tutorials. Then the regex looks like:
.+?(\d\d\.\d\d\.(2015|2016|2017)?).+?
But the result is still not what I am looking for:
BEGIN:VNOTE
VERSION:1.1
21.03.20.04.18.05.18.06.18.07.14.08.15.09.15.10.
13.11.13.12.12.01.03.02.06.03.04.04.20150A0=
03.06.201503.07.201502.08.201530.08.20150A28.09=
28.10.201525.11.201528.12.201524.01.20160A
DCREATED:20171118T075601
X-IRMC-LUID:150
END:VNOTE
For someone who is familiar with regex I am pretty sure this is very easy to solve, but I don't get it. It's very confusing when you are new to regex. I tried to find a hint in some tutorials or stackoverflow posts, but all I found is this: Notepad++ how to extract only the text field which is needed?
But it doesn't work for me. I assume it might have something to do with the fact that my text file is not one single line.
I have my example on regex101 too.
I would be very thankful if maybe someone can give me a hint what else I can try.
Edit: I would like to detect the dates with the regex and as a result have a list with only the dates (maybe it is called substitute?)
Edit 2: Sorry for not mentioning it earlier: I just want to use the regex in e.g. Notepad++ or an online regex test website. Just to get the result of the dates and save the result in a new txt-file. I don't want to use the regex in an programming language. My apologies for not being precisely before.
Edit 3: The result should be a list with the dates, and each date in a new line:
I want to extract all dates, so that the final list is like that:
18.07.
14.08.
15.09.
15.10.
I suggest this pattern:
(?:.*?|\G)(\d\d\.\d\d\.(?:\d{4})?)
This makes use of the \G flag that, in this case, allows for multiple matches from the very start of the match without letting any single unmatched character in the text, thus allowing the removal of all but what's wanted.
If you want to remove the extra matches as well, add |.* at the end:
(?:.*?|\G)(\d\d\.\d\d\.(?:\d{4})?)|.*
regex101 demo
In N++, make sure the options underlined are selected, and that the cursor is at the beginning. In the picture below, I replaced then undid the replacement, only to show that matches were identified (16 replacements).
You can try using the following pattern:
\d{2}\.\d{2}\.(?:\d{4})?
This will match day.month dates of the form 18.07., but it also allows such a date to be followed by a four digit year, e.g. 18.07.2017. While it would be nice to make the pattern more restrictive, to avoid false fire matches, I do not see anything obvious which can be added to the above pattern. Follow the demo link below to see the pattern in action.
Demo

REGEX number not in a list failing with a long list

I have a list of the following numbers and want a Regular expression that matches when a number is not in the list.
0,1,2,3,4,9,11,12,13,14,15,16,18,19,250
I have written the following REGEX statement.
^(?!.*(0|1|2|3|4|9|11|12|13|14|15|16|18|19|250)).*$
The problem is that it correctly gives a match for 5,6,7,8 etc but not for 17 or 251 for example.
I have been testing this on the online REGEX simulators.
This should resolve your issue..
^(?!\D*(0|1|2|3|4|9|11|12|13|14|15|16|18|19|250)\b).*$
In your earlier regex you were basically saying eliminate all numbers that start with 0/1/2/3/4/9!
So your original regex would actually match 54/623/71/88 but not the others. Also the 11-19 and 250 in the list were rendered useless.
Although as others have I would also recommend you to not use regex for this, as I believe it is an overkill and a maintenance nightmare!
Also an extra note "Variable length look arounds are very inefficient too" vs regular checks.
I would do \b\d+\b to get each number in the string and check if they are in your list. It would be way faster.
You can use the discard technique by matching what you do not want and capturing what you really want.
You can use a regex like this:
\b(?:[0-49]|1[1-689]|250)\b|(\d+)
Here you can check a working demo where in blue you have the matches (what you don't want) and in green the content you want. Then you have to grab the content from the capturing group
Working demo
Not sure what regex engine you are using, but here I created a sample using java:
https://ideone.com/B7kLe0

Regex to strictly match a string containing strings with a separator?

I have multiple elements popup, email and webhook.
They can come in a string formated like :
popup|email|webhook
email|webhook
webhook
email
email|webhook
popup|webhook
popup|email
popup
I actually got a regex ^(?:popup){0,1}?\|?(?:email){0,1}?\|?(?:webhook){0,1}?$ but it will match popup|email|webhook as well as popupemail|webhook.
Is there a way to ensure elements are separated with my separatator | ?
I also had (?>(?>(?>popup\|?){0,1}?email\|?){0,1}?webhook){0,1}? but this is not a solution obvisously as it will work in one direction only, I'm nearly sure this is easily solvable but I dont know in wich way to look in the Regex world.
You just need to add word boundaries to make sure that two words are never together.
^(?:popup)?\b\|?\b(?:email)?\b\|?\b(?:webhook)?$
Demo