Andrew Vershinin
Andrew Vershinin

Reputation: 1968

Why does this regexp for IPv4 doesn't work?

So this is the regex I've made: ^(([01]?\d{1,2})|(2(([0-4]\d)|(5[0-5])))\.){3}(([01]?\d{1,2})|(2(([0-4]\d)|(5[0-5]))))$

I have used several sites to break it down and it seems that it should work, but it doesn't. The desired result is to match any IPv4 - four numbers between 0 and 255 delimited by dots.

As an example, 1.1.1.1 won't give you a match. The purpose of this question is not to find out a regex for IPv4 address, but to find out why this one, which seems correct, is not.

Upvotes: 1

Views: 100

Answers (2)

Scott Weaver
Scott Weaver

Reputation: 7351

to fix yours up, just account for the "decimal" after each of the first three groups:

((2[0-4]\d|25[0-5]|[01]?\d{1,2})\.){3}(2[0-4]\d|25[0-5]|[01]?\d{1,2})

(*note that I reversed the order of the 2xx vs 1xx tests as well - prefer SPECIAL|...|NORMAL, or more restrictive first, when using alternations like this)

see it in action

Upvotes: 0

Mr. Llama
Mr. Llama

Reputation: 20889

The literal . is only part of the 200-255 section of the capture group: railroad diagram.

Here's (([01]?\d{1,2})|(2([0-4]\d)|(5[0-5]))\.) formatted differently to help you spot the reason:

(
    ([01]?\d{1,2})
    |
    (2([0-4]\d)|(5[0-5])) \.
)

You're matching 0-199 or 200-255 with a dot. The dot is conditional on matching 200-255.

Additionally, as @SebastianProske pointed out, 2([0-4]\d)|(5[0-5]) matches 200-249 or 50-55, not 200-255.

You can fix your regex by adding capturing groups, but ultimately I would recommend not reinventing the wheel and using A) a pre-existing regex solution or B) parse the IPv4 address by splitting on dots. The latter method being easier to read and understand.

Upvotes: 3

Related Questions