CruelEngine
CruelEngine

Reputation: 2841

Regexp to validate ip address with last digit as non zero

I have a regex that i ended up using from one of the answer here in SO . Basically my regex must validate ipv4 address with mask .

So i ended up using the below regex :

(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/([1-9]|1[0-9]|2[0-9]|3[0-2]|(((128|192|224|240|248|252|254)\.0\.0\.0)|(255\.(0|128|192|224|240|248|252|254)\.0\.0)|(255\.255\.(0|128|192|224|240|248|252|254)\.0)|(255\.255\.255\.(0|128|192|224|240|248|252|254))))

Now my challenge is to not allow 0 in the last digit of ip i.e , 192.168.6.10/mask is valid but 192.168.6.0/mask is invalid

So i modified the above regexp to something like this :

(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[1-9]?)/([1-9]|1[0-9]|2[0-9]|3[0-2]|(((128|192|224|240|248|252|254)\.0\.0\.0)|(255\.(0|128|192|224|240|248|252|254)\.0\.0)|(255\.255\.(0|128|192|224|240|248|252|254)\.0)|(255\.255\.255\.(0|128|192|224|240|248|252|254))))

but 192.168.6.0 is always valid when testing with Angular Validators.pattern

Any idea where i'm going wrong ?

EDIT List of IPs & its validity :

192.168.6.6/24 is valid 192.168.6.6/24 is valid 192.168.6.24/24 is valid

192.168.6.0/24 invalid 192.168.6.0/255.255.255.0 is invalid

Upvotes: 1

Views: 664

Answers (4)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 627419

You want to avoid matching any IP with the last octet set to 0.

You may use

ipAddress : FormControl = new FormControl('' , Validators.pattern(/^(?!(?:\d+\.){3}0(?:\/|$))(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/(?:[1-9]|1[0-9]|2[0-9]|3[0-2]|(?:(?:128|192|224|240|248|252|254)\.0\.0\.0|255\.(?:0|128|192|224|240|248|252|254)\.0\.0|255\.255\.(?:0|128|192|224|240|248|252|254)\.0|255\.255\.255\.(?:0|128|192|224|240|248|252|254)))$/));

Here is the regex demo

The main addition is the lookahead after ^ that is executed once at the start of a string. The (?!(?:\d+\.){3}0(?:\/|$)) pattern is a negative lookahead that fails the match if, immediately to the right of the current location (string start), there are:

  • (?:\d+\.){3} - three repetitions of 1+ digits and a dot
  • 0 - a zero
  • (?:\/|$)) - / or (|) end of string ($).

Notice I defined the pattern using a regex literal notation (/regex/) and I had to add ^ (string start) and $ (string end) anchors since the regex was no longer anchored by default. Also, to escape special chars in a regex literal notation, you only need one backslash, not two.

Upvotes: 1

splash58
splash58

Reputation: 26153

Suppose that the last part cannot be written 000 and 00 but just 0. Then you can you such regex

^(?:(?:2(?:5[0-5]|[0-4]\d)|1?\d?\d)\.){3}(?:(?:2(?:5[0-5]|[0-4]\d)|1?\d\d|[1-9]))$

Where diff between the first groups and the last one that one-digit value should be from 1 to 9

demo

Upvotes: 1

Tim Biegeleisen
Tim Biegeleisen

Reputation: 522636

One possible approach here is simple, and just involves adding a negative lookbehind at the very end of the pattern (?<!\.0), which asserts that .0 is not the immediately preceding term in the IP address. Applying this to your correctly working pattern from the comments above, we get:

^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}
    (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/
    ([1-9]|1[0-9]|2[0-9]|3[0-2]|(((128|192|224|240|248|252|254)\.0\.0\.0)|
    (255\.(0|128|192|224|240|248|252|254)\.0\.0)|
    (255\.255\.(0|128|192|224|240|248|252|254)\.0)|
    (255\.255\.255\.(0|128|192|224|240|248|252|254))))(?<!\.0)$

Demo

The downside is that your JavaScript engine may not yet support negative lookbehind syntax just yet.

Upvotes: 0

mkHun
mkHun

Reputation: 5921

You can try with this pattern

^(?:[1-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.(?:[1-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.(?:[1-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.(?:2[0-5][1-5]|[1-9]|1[0-9][1-9]|[1-9][1-9])$

Online demo

For the last numbers you have check with this

(?:2[0-5][1-5]|[1-9]|1[0-9][1-9]|[1-9][1-9])

Upvotes: 0

Related Questions