How to match the 2 last numbers of an IP adress? - regex

i don't know what i'm missing ^^
I'm on bash script, i tested it with https://regex101.com/
Here is some ip adress:
192.168.23.84
192.168.112.34
192.168.43.227
And i want to match only the numbers that are not by group of 3, i've tried:
\.([0-9]{2})\.|\.([0-9]{1})\.|\.([0-9]{2})$|\.([0-9]{1})$
I don't know why i'm not matching the two last numbers, Is there a better solution ?

^(\d{1,2})\.|\.(\d{1,2})\.|\.(\d{1,2})$
You've got 3 cases : 1|2 digits after the start followed by a dot, 1|2 digits betweens dots, 1|2 digit after a dot at the end of the line.
With this solution you'll have 3 groups and you won't be able to known which part for the middle group has not 3 digits. If you want 4 groups use this one :
(?:^(\d{1,2})\.)|(?:^\d{3}\.(\d{1,2})\.)|(?:\.(\d{2})$)|(?:\.(\d{2})\.\d{2,3})
Edit : https://regex101.com/r/eAc8XX/1
Be aware that I'm not looking for a valid IPv4 with theses regex.

Related

How to select with regex this character?

For the example i have these four ip address:
10.100.0.11; wrong
10.100.1.12; good
10.100.11.4; good
10.100.44.1; wrong
The task has simple rules. In the 3rd place cant be 0, and the 4rd place cant be a solo 1.
I need to select they from an ip table in different routers and i know only this rules.
My solution:
^(10.100.[1-9]{1,3}.[023456789]{1,3})$
but in this case every number with 1 like 10, 100 etc is missing, so in this way this solution is wrong.
^(10.100.[1-9]{1,3}.[1-9]{2,3})$
This solve the problem of the single 1, but make another one.
From the rules you have given, this regex should work:
10\.100\.([123456789]\d*|\d{2,})\.([^1]$|\d{2,})
it also matches 3rd position number containing a 0 but not in the first place.
so 10.100.10.4 will match as well as 10.100.02.4
I don't know if it's the intended behavior since I'm not familiar with ip adress.
The last part \.([^1]$|\d{2,}) reads like this:
"after the 3rd dot is either
a character which is not 1 followed by the end of the line
or two or more digits"
If you want to avoid malformed string containing non-digit character like 10.100.12.a to be match you should replace [^1] by [023456789] or lazier (and therefore better ;) by [02-9]
I use https://regex101.com to debug regex. It's just awesome.
Here is your regex if you want to play with it
You might use
^10\.100\.[1-9]{1,3}\.(?:[02-9]|\d{2,3})$
The pattern matches
^ Start of string
10\.100\. Match 10.100. (note to escape the dot to match it literally)
[1-9]{1,3} Match 3 times a digit 1-9
\. Match a dot
(?: Non capture group
[02-9] Match a digit 0 or 2-9
| Or
\d{2,3} Match 2 or 3 digits 0-9
) Close the group
$ End of string
Regex demo

Notepadd ++ Insert hyphen if more than 5 numbers

I have a large list of zip codes. Most of the zip codes are 5 digits but some are 9 digits.
I need to insert a hyphen after the 5th number but only if there are more than 5 numbers.
I can find those with 9 digits with
(^\d{9})
but I am unsure on how to replace.
With capturing groups and substitution we can achieve this.
Find what: (\d{5})(\d{4})
Replace with: $1-$2
This finds 5 digits followed by 4 digits and creates two capturing groups (one chunk with the first 5 digits and another chunk with the following 4). The '$'-sign followed by a number is a substitution. Here we are saying: Paste the first capturing group, insert a hyphen and paste the second capturing group.
Example: https://regex101.com/r/KnzTus/1

Regex - Capturing group to return null for a non matching string

I am learning regex now. My requirement is simple. This is my regex.
([0-9]*)(\.)([0-9]*)
and my input is like this.
1.9
2.8
4.76
3
7.8
I just want to return only decimal portion. I am currently printing 3rd capturing group $3. Output is like this.
9
8
76
3
8
But my expected output is this.
9
8
76
8
Please tell me how to achieve this. Whenever the string is not matching my $3 returns entire string. I want it to return null or any other default value(like '0'). Is it possible to achieve this using lookarounds? If so, how?
The chosen answer is not actually a good answer since it just works in some cases, but not all.
The answer given makes regex looks for two different accepted patterns (separated by the "or" | character):
(\d*)(\.)(\d+) and (^\d+$)()()
The first pattern looks for:
Group 1: a number digit zero or more times (\d*);
Group 2: a dot at least one time (\.);
Group 3: a number one or more times (\d+);
The second pattern looks for:
Group 1: a text that has only at least one number from begging to end, with no other characters;
Group 2 and 3: nothing;
The first problem with this approach is that you are requiring that the number has at least one number on the decimals in the fist pattern option, when it's the exact opposite of what you want. The second problem is that you are hard-coding an empty answer on the last two groups of the second option.
The correct way would be to capture and receive exactly what it is in each group, being the first group the integer value, the second group the dot and the third value the decimals.
You must think of each group:
Group 1: Numbers, so \d. Is .1 an option, or it should only grab 0.1? Both are options in the previous answer. If you want a null integer, then you should use * (zero or more occurrences). If you don't want a null integer, then use + (one of more occurrences).
Group 2: The dot. Since dot is a special character, we need to use the escape character like \.. The dot should be optional, right? So you should use the ? character (zero or one occurrences).
Group 3 is like group 1.
So the correct answer should be: (\d*)(\.?)(\d*)
This simple answer will give you the integer in $1, the dot in $2 and the decimals in $3 and nothing when there's nothing.
So, in the examples
$1 would give you:
1
2
4
3
7
$2 would give you:
.
.
.
.
and $3 would give you:
9
8
76
8
This would be a simpler way to read, understand and the regex wouldn't need to check each part of the string for two different patterns.
I was able to achieve this using following regex.
Regex: (\d*)(\.)(\d+)|(^\d+$)()()
Demo: Regex101 Demo
This takes into account only two cases.
Numbers with decimal part are matched and returned in captured in group $3.
Numbers with no decimal part so zero width is captured in group $3.
Note: If there are more test cases please specify in question. I was not able to put this in comment due to low reputation.

Regex for 5 digit number with optional characters

I am trying to create a regex to validate a field where the user can enter a 5 digit number with the option of adding a / followed by 3 letters. I have tried quite a few variations of the following code:
^(\d{5})+?([/]+[A-Z]{1,3})?
But I just can't seem to get what I want.
For instance l would like the user to either enter a 5 digit number such as 12345 with the option of adding a forward slash followed by any 3 letters such as 12345/WFE.
You probably want:
^\d{5}(?:/[A-Z]{3})?$
You might have to escape that forward slash depending on your regex flavor.
Explanation:
^ - start of string anchor
\d{5} - 5 digits
(?:/[A-Z]{3}) - non-capturing group consisting of a literal / followed by 3 uppercase letters (depending on your needs you could consider making this a capturing group by removing the ?:).
? - 0 or 1 of what precedes (in this case that's the non-capturing group directly above).
$ - end of string anchor
All in all, the regex looks like this:
You can use this regex
/^\d{5}(?:\/[a-zA-Z]{3})?$/
^\d{5}(?:/[A-Z]{3})?$
Here it is in practice (this is a great site to test your regexes):
http://regexr.com?36h9m
^(\d{5})(\/[A-Z]{3})?
Tested in rubular

Why does this not match my example?

as I go through the regex101 quiz/lessons, I am supposed to match an IP address (without leading zeros).
Now the following
^[^0]+[0-9]+\\.[^0]+[0-9]+\\.[^0]+[0-9]+\\.[^0]+[0-9]+$
matches 23.34.7433.33
but fails to match single digit numbers like 1.2.3.4
Why is this so, when my + is supposed to match "1 to infinite" times...?
You are in fact matching more than 2 digits for each number in the IP address because you have:
[^0]+[0-9]+
[^0]+ matches at least one character, and [0-9]+ matches at least 1 character. Both will match 'at least 2 characters' (characters being in scope of the character classes).
Also 23.34.7433.3 doesn't match your regex for the reason I stated above.
And you might try this regex for the purpose you stated:
^(?:[1-9][0-9]{0,2}\.){3}[1-9][0-9]{0,2}$
[1-9][0-9]{0,2} will match up to 3 digits, with a non leading 0.
EDIT: You mentioned in a comment that 0.0.0.0 (single digit zeroes) are to be accepted as well. The modified regex from above would be:
^(?:(?:[1-9][0-9]{0,2}|0)\.){3}(?:[1-9][0-9]{0,2}|0)$
Assuming you want to check an IPv4, I suggest you this pattern:
^(?<nb>2(?>[0-4][0-9]|5[0-5])|1[0-9]{2}|[1-9]?[0-9])(?>\.\g<nb>){3}$
I have defined a named subpattern nb to make the pattern shorter, but if you prefer, you can rewrite all and replace \g<nb>:
^(?>2(?>[0-4][0-9]|5[0-5])|1[0-9]{2}|[1-9]?[0-9])(?>\.(?>2(?>[0-4][0-9]|5[0-5])|1[0-9]{2}|[1-9]?[0-9])){3}$
Numbers greater than 255 are not allowed.
pattern details:
The goal is to describe what is allowed:
numbers with 3 digits that begins with "2" can be followed by a digit in [0-4] and a digit in [0-9] OR by 5 and a digit in [0-5] because it can exceed 255.
numbers with 3 digits that begins with "1" can be followed by any two digits.
any number with 2 digits that doesn't begin with "0"
any number with 1 digit (zero included)
If I add one by one these rules, I obtain
2(?>[0-4][0-9]|5[0-5])
2(?>[0-4][0-9]|5[0-5]) | 1[0-9]{2}
2(?>[0-4][0-9]|5[0-5]) | 1[0-9]{2} | [1-9][0-9]
2(?>[0-4][0-9]|5[0-5]) | 1[0-9]{2} | [1-9][0-9] | [0-9]
Now I have a definition for allowed numbers. I can reduce a little the size of the pattern replacing [1-9][0-9] | [0-9] by [1-9]?[0-9]
Then you only have to add the dot repeat the subpattern four times: x.x.x.x
But since there is only three dots, I write the first number and I repeat 3 times a group that contains a dot and a number:
2(?>[0-4][0-9]|5[0-5])|1[0-9]{2}|[1-9]?[0-9] # the first number
(?>\.2(?>[0-4][0-9]|5[0-5])|1[0-9]{2}|[1-9]?[0-9]){3} # the group repeated 3 times
To be sure that the string doesn't contain anything else that the IP I described, I add anchors for the start of string ^ and for the end of string $, then the string begins and ends with the IP.
To reduce the size of a pattern you can define a named group which allows to reuse the subpattern it contains,
Then you can rewrite the pattern like this:
^
(?<nb> 2(?>[0-4][0-9]|5[0-5])|1[0-9]{2}|[1-9]?[0-9] ) # named group definition
(?> \. \g<nb> ){3} # \g<nb> is the reference to the subpattern named nb
$
[0-9]+ should be [0-9]*
* matches 0 or more.
+ matches 1 or more.
You already have the case [^0] <--- this actually wrong because it will match letters also.
besides that it will match the first character that's NOT zero then at least one number after that.
It should be written as
[1-9][0-9]*
This essentially checks the first letter and sees if its a number that's between 1-9 then the next numbers(0 nums to infinite nums) after that is a number 0-9.
Then this will come out to.
^[1-9][0-9]*\.[1-9][0-9]*\.[1-9][0-9]*\.[1-9][0-9]*$
Edit live on Debuggex
cleaning it up.
^(?:[1-9][0-9]*\.){3}[1-9][0-9]*$
this should work...
^(?:[1-9][0-9]*\.|[0-9])(?:[1-9][0-9]*\.|[0-9])(?:[1-9][0-9]*\.|[0-9])(?:[1-9][0-9]*|[0-9])$
cleaned up.
^(?:(?:[1-9][0-9]*|0)\.){3}(?:[1-9][0-9]*|0)$
Your regex would match ABCDEFG999.FOOBSR888 etc, because [^0] is any character other than a zero, and bith character classes are required by the +.
I think you want this:
^[1-9]\d*(\\.[1-9]\d*){3}$
having replaced various verbose expressions with their equivalent, this is 4 groups of digits each starting with a non-zero.
Actually the problem is far more complicated, because your approach (once corrected) allows 999.999.999.999, which is not a valid IP.
It might be because you need at least two digits between two dots '.'
try using this pattern: ^[^0]+[0-9]*\.[^0]+[0-9]*\.[^0]+[0-9]*\.[^0]+[0-9]*$
to match ip address you should use this pattern:
\b(?:\d{1,3}.){3}\d{1,3}\b
taken from here:
http://www.regular-expressions.info/examples.html