Matthieu Cartier
Matthieu Cartier

Reputation: 2741

Validating IPv4 addresses with regexp

I've been trying to get an efficient regex for IPv4 validation, but without much luck. It seemed at one point I had had it with (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?(\.|$)){4}, but it produces some strange results:

$ grep --version
grep (GNU grep) 2.7
$ grep -E '\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?(\.|$)){4}\b' <<< 192.168.1.1
192.168.1.1
$ grep -E '\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?(\.|$)){4}\b' <<< 192.168.1.255
192.168.1.255
$ grep -E '\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?(\.|$)){4}\b' <<< 192.168.255.255
$ grep -E '\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?(\.|$)){4}\b' <<< 192.168.1.2555
192.168.1.2555

I did a search to see if this had already been asked and answered, but other answers appear to simply show how to determine 4 groups of 1-3 numbers, or do not work for me.

Upvotes: 237

Views: 652850

Answers (30)

Jpsy
Jpsy

Reputation: 20852

I would consider this the best compromise between readability and conciseness:

^((25[0-5]|2[0-4]\d|[01]?\d?\d)\.?\b){4}$

Here is an extended version that also accepts CIDR-notation for network ranges (i.e. 123.123.123.123/24):

^((25[0-5]|2[0-4]\d|[01]?\d?\d)\.?\b){4}(\/(3[0-2]|[0-2]?\d))?$

Upvotes: 1

bobble bubble
bobble bubble

Reputation: 18490

The shortest pattern is not necessarily the most efficient. I prefer

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

which is a good tradeoff between pattern-length and efficiency.

Here is a demo at regex101

This pattern works by use of a \b word boundary and making the dot optional. The word boundary will still require a dot between each 0-255. Placement of \b disallows a dot at the ^ start.

Certainly by use of ( capturing ) instead of (?: non-capturing ) groups four characters can be spared but why capture anything without reason? No part gets reused or would be extracted.

The only reason that makes sense would be, if non-capturing groups are not supported.


Without validating 0-255 and allowing any one to three digits: ^(?:\b\.?\d{1,3}){4}$

Upvotes: 2

WersV
WersV

Reputation: 15

Just try using URL constructor

const validateIPAddress = (ipAddress) => {
  try {
    new URL(`http://${ipAddress}`);
    return true;
  } catch (error) {
    alert("Wrong IP Address");
    return false;
  }
}

Upvotes: 0

don't reinvent the wheel ;)

the best way is to use well written and tested library

npm @sideway/address has 6M weekly downloads

import { ipRegex } from "@sideway/address";

const { regex } = ipRegex({ version: ['ipv4'], cidr: 'forbidden' });

the regex for ipv4 without cidr is:

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

unit tested on:

const validIPv4sWithoutCidr = [
  '0.0.0.0',
  '255.255.255.255',
  '127.0.0.1',
  '192.168.2.1',
  '0.0.0.3',
  '0.0.0.7',
  '0.0.0.15',
  '0.0.0.31',
  '0.0.0.63',
  '0.0.0.127',
  '01.020.030.100',
  '0.0.0.0',
  '00.00.00.00',
  '000.000.000.000'
];

but you can easily with (without) options match other versions and be sure it covers all possibilities

import { ipRegex } from "@sideway/address";

const { regex } = ipRegex();

/^(?:(?:(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])(?:\/(?:\d|[1-2]\d|3[0-2]))?|(?:(?:[\dA-Fa-f]{1,4}:){6}(?:[\dA-Fa-f]{1,4}:[\dA-Fa-f]{1,4}|(?:(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|::(?:[\dA-Fa-f]{1,4}:){5}(?:[\dA-Fa-f]{1,4}:[\dA-Fa-f]{1,4}|(?:(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(?:[\dA-Fa-f]{1,4})?::(?:[\dA-Fa-f]{1,4}:){4}(?:[\dA-Fa-f]{1,4}:[\dA-Fa-f]{1,4}|(?:(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(?:(?:[\dA-Fa-f]{1,4}:){0,1}[\dA-Fa-f]{1,4})?::(?:[\dA-Fa-f]{1,4}:){3}(?:[\dA-Fa-f]{1,4}:[\dA-Fa-f]{1,4}|(?:(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(?:(?:[\dA-Fa-f]{1,4}:){0,2}[\dA-Fa-f]{1,4})?::(?:[\dA-Fa-f]{1,4}:){2}(?:[\dA-Fa-f]{1,4}:[\dA-Fa-f]{1,4}|(?:(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(?:(?:[\dA-Fa-f]{1,4}:){0,3}[\dA-Fa-f]{1,4})?::[\dA-Fa-f]{1,4}:(?:[\dA-Fa-f]{1,4}:[\dA-Fa-f]{1,4}|(?:(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(?:(?:[\dA-Fa-f]{1,4}:){0,4}[\dA-Fa-f]{1,4})?::(?:[\dA-Fa-f]{1,4}:[\dA-Fa-f]{1,4}|(?:(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(?:(?:[\dA-Fa-f]{1,4}:){0,5}[\dA-Fa-f]{1,4})?::[\dA-Fa-f]{1,4}|(?:(?:[\dA-Fa-f]{1,4}:){0,6}[\dA-Fa-f]{1,4})?::)(?:\/(?:0{0,2}\d|0?[1-9]\d|1[01]\d|12[0-8]))?|v[\dA-Fa-f]+\.[\w-\.~!\$&'\(\)\*\+,;=:]+(?:\/(?:0{0,2}\d|0?[1-9]\d|1[01]\d|12[0-8]))?)$/

Upvotes: 1

Jonathzen
Jonathzen

Reputation: 1

-bash-3.2$ echo "191.191.191.39" | egrep 
  '(^|[^0-9])((2([6-9]|5[0-5]?|[0-4][0-9]?)?|1([0-9][0-9]?)?|[3-9][0-9]?|0)\.{3}
     (2([6-9]|5[0-5]?|[0-4][0-9]?)?|1([0-9][0-9]?)?|[3-9][0-9]?|0)($|[^0-9])'

>> 191.191.191.39

(This is a DFA that matches the entire addr space (including broadcasts, etc.) and nothing else.

Upvotes: 0

Etienne Gautier
Etienne Gautier

Reputation: 3207

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

Demo

Upvotes: 5

Serious Angel
Serious Angel

Reputation: 1555

Considering some variants suggested, \d and \b may not be supported. Hence, just in case:

IPv4 address

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

Test: https://debuggex.com/r/izHiog3KkYztRMSJ

graph

Upvotes: 2

Danail Gabenski
Danail Gabenski

Reputation: 3630

Best for Now (43 chars)

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

This version shortens things by another 6 characters while not making use of the negative lookahead, which is not supported in some regex flavors.

Newest, Shortest, Least Readable Version (49 chars)

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

The [0-9] blocks can be substituted by \d in 2 places - makes it a bit less readable, but definitely shorter.

Even Newer, even Shorter, Second least readable version (55 chars)

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

This version looks for the 250-5 case, after that it cleverly ORs all the possible cases for 200-249 100-199 10-99 cases. Notice that the |) part is not a mistake, but actually ORs the last case for the 0-9 range. I've also omitted the ?: non-capturing group part as we don't really care about the captured items, they would not be captured either way if we didn't have a full-match in the first place.

Old and shorter version (less readable) (63 chars)

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

Older (readable) version (70 chars)

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

It uses the negative lookahead (?!) to remove the case where the ip might end with a .

Alternative answer, using some of the newer techniques (71 chars)

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

Useful in regex implementations where lookaheads are not supported

Oldest answer (115 chars)

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

I think this is the most accurate and strict regex, it doesn't accept things like 000.021.01.0. it seems like most other answers here do and require additional regex to reject cases similar to that one - i.e. 0 starting numbers and an ip that ends with a .

Upvotes: 268

Grant
Grant

Reputation: 1

^\\s*[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]\\s*

Upvotes: -4

Rosta Kosta
Rosta Kosta

Reputation: 323

Find a valid ip address in the text is a very difficult problem


I have a regexp, that match (extract) valid ip addresses from strings in text files.

my regexp

\b(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])\.)(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){2}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\b
  • \b word boundary
  • (?: - means start non capturing group
  • ^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])\.) - string must start with first right octet with dot char
    • (?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9]) - find first right octet - (firt octet can not start with - 0)
  • (?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){2} - find next right two octets with dot string
  • (?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\b - string must end with right fourth octet (now zero char is allowed)

But this ip regexp has a minority false positive matches:

https://regexr.com/69dk7

regexp for mostly right match for ip addresses

Find or extract valid ip address from text file with only regexp is impossible. Without checking another conditions you always get false positive matches.

Solution


I write one liner perl for extract ip addresses from text files. It has this conditions:

  • when the ip address is at the beginning of the line, the next char is one or multiple whitespace char (space, tab, new line...)
  • when ip address is at end of line, the new line is next char and before ip address is one or multiple whitespace chars
  • in middle of text - before and after ip address is one or multiple whitespace chars

The consequence is that perl not match strings like https://84.25.74.125 and another URI strings. Or ip addres at the end of line with dot char at the end. But it find any valid ip address in the text.

perl one liner solution:

$ cat ip.txt | perl -lane 'use warnings; use strict; for my $i (@F){if ($i =~/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])\.)(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){2}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/) { print $i; } }'
36.42.84.233
158.22.45.0
36.84.84.233
12.0.5.4
1.25.45.36
255.3.6.5
4.255.2.1
127.0.0.1
127.0.0.5
126.0.0.1

testing text file:

$ cat ip.txt
36.42.84.233 stop 158.22.45.0 and 56.32.58.2.
25.36.84.84abc and abc2.4.8.2 is error.
1.2.3.4_
But false positive is 2.2.2.2.2.2.2.2 or 1.1.1.1.1
http://23.54.212.1:80
https://89.35.248.1/abc
36.84.84.233 was 25.36.58.4/abc/xyz&158.133.26.4&another_var
and 42.27.0.1:8333 in http://212.158.45.2:26
0.25.14.15 ip can not start with zero
2.3.0
abc 12.0.5.4
1.25.45.36
12.05.2.5
256.1.2.5
255.3.6.5
4.255.2.1
4.256.5.6
127.0.0.1 is localhost.
this ip 127.0.0.5 is not localhost
126.0.0.1

Appendix


For people from another planets for whom the strings 2130706433, 127.1, 24.005.04.52 is a valid ip address I have a message: Try to find a solution yourself!!!

Upvotes: 3

manjunath
manjunath

Reputation: 35

To validate any IP address in the valid range 0.0.0.0 to 255.255.255.255 can be written in very simple form as below.

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

Upvotes: 1

SsNipeR1
SsNipeR1

Reputation: 21

My solution here:

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

This regex will match:

0.0.0.0
255.255.255.255
123.123.123.123
127.0.0.1
192.168.0.1

But it will NOT match:

192.168.1.01
256.256.256.256
01.01.01.01

Upvotes: 0

abhijithvijayan
abhijithvijayan

Reputation: 931

Here is a better one with passing/failing IPs attached

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

Accepts

127.0.0.1
192.168.1.1
192.168.1.255
255.255.255.255
10.1.1.1
0.0.0.0

Rejects

1.1.1.01
30.168.1.255.1
127.1
192.168.1.256
-1.2.3.4
1.1.1.1.
3...3
192.168.1.099

Upvotes: 6

whoisYeshua
whoisYeshua

Reputation: 21

This pattern unclude 52 symbols and accept cuncks started with zero.

/^(?:(?:[01]?\d?\d|2[0-4]\d|25[0-5])(?:\.|$)){4}\b$/

Upvotes: 0

Alvin567
Alvin567

Reputation: 335

Try this

^(127|10).[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}"

Upvotes: 0

Valerij
Valerij

Reputation: 27738

IPv4 address (accurate capture) Matches 0.0.0.0 through 255.255.255.255, but does capture invalid addresses such as 1.1.000.1 Use this regex to match IP numbers with accuracy. Each of the 4 numbers is stored into a capturing group, so you can access them for further processing.

\b
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
\b

taken from JGsoft RegexBuddy library

Edit: this (\.|$) part seems weird

Upvotes: 16

Enginer
Enginer

Reputation: 3128

^((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]?)$

Accept:

127.0.0.1
192.168.1.1
192.168.1.255
255.255.255.255
0.0.0.0
1.1.1.01        # This is an invalid IP address!

Reject:

30.168.1.255.1
127.1
192.168.1.256
-1.2.3.4
1.1.1.1.
3...3

Try online with unit tests: https://www.debuggex.com/r/-EDZOqxTxhiTncN6/1

Upvotes: 119

sZpak
sZpak

Reputation: 247

My [extended] approach → regexp for space-separated IP addresses:

((((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\\.(?=\\d)|(?!\\d))){4})( (?!$)|$))+

Uses PCRE look-ahead.

Upvotes: 0

sanket patel
sanket patel

Reputation: 499

Valid regex for IPV4 address for Java

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

Upvotes: 2

Arhan Ashik
Arhan Ashik

Reputation: 71

I tried to make it a bit simpler and shorter.

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

If you are looking for java/kotlin:

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

If someone wants to know how it works here is the explanation. It's really so simple. Just give it a try :p :

 1. ^.....$: '^' is the starting and '$' is the ending.

 2. (): These are called a group. You can think of like "if" condition groups.

 3. |: 'Or' condition - as same as most of the programming languages.

 4. [01]?\d{1,2}: '[01]' indicates one of the number between 0 and 1. '?' means '[01]' is optional. '\d' is for any digit between 0-9 and '{1,2}' indicates the length can be between 1 and 2. So here the number can be 0-199.

 5. 2[0-4]\d: '2' is just plain 2. '[0-4]' means a number between 0 to 4. '\d' is for any digit between 0-9. So here the number can be 200-249.

 6. 25[0-5]: '25' is just plain 25. '[0-5]' means a number between 0 to 5. So here the number can be 250-255.

 7. \.: It's just plan '.'(dot) for separating the numbers.

 8. {3}: It means the exact 3 repetition of the previous group inside '()'.

 9. ([01]?\d{1,2}|2[0-4]\d|25[0-5]): Totally same as point 2-6

Mathematically it is like:

(0-199 OR 200-249 OR 250-255).{Repeat exactly 3 times}(0-199 OR 200-249 OR 250-255)

So, as you can see normally this is the pattern for the IP addresses. I hope it helps to understand Regular Expression a bit. :p

Upvotes: 1

Arhan Ashik
Arhan Ashik

Reputation: 71

I tried to make it a bit simpler and shorter.

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

If you are looking for java/kotlin:

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

If someone wants to know how it works here is the explanation. It's really so simple. Just give it a try :p :

 1. ^.....$: '^' is the starting and '$' is the ending.

 2. (): These are called a group. You can think of like "if" condition groups.

 3. |: 'Or' condition - as same as most of the programming languages.

 4. [01]?\d{1,2}: '[01]' indicates one of the number between 0 and 1. '?' means '[01]' is optional. '\d' is for any digit between 0-9 and '{1,2}' indicates the length can be between 1 and 2. So here the number can be 0-199.

 5. 2[0-4]\d: '2' is just plain 2. '[0-4]' means a number between 0 to 4. '\d' is for any digit between 0-9. So here the number can be 200-249.

 6. 25[0-5]: '25' is just plain 25. '[0-5]' means a number between 0 to 5. So here the number can be 250-255.

 7. \.: It's just plan '.'(dot) for separating the numbers.

 8. {3}: It means the exact 3 repetition of the previous group inside '()'.

 9. ([01]?\d{1,2}|2[0-4]\d|25[0-5]): Totally same as point 2-6

Mathematically it is like:

(0-199 OR 200-249 OR 250-255).{Repeat exactly 3 times}(0-199 OR 200-249 OR 250-255)

So, as you can see normally this is the pattern for the IP addresses. I hope it helps to understand Regular Expression a bit. :p

Upvotes: 1

congacon
congacon

Reputation: 66

For number from 0 to 255 I use this regex:

(([0-9])|([1-9][0-9])|(1([0-9]{2}))|(2[0-4][0-9])|(25[0-5]))

Above regex will match integer number from 0 to 255, but not match 256.

So for IPv4 I use this regex:

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

It is in this structure: ^(N)((\.(N)){3})$ where N is the regex used to match number from 0 to 255.
This regex will match IP like below:

0.0.0.0
192.168.1.2

but not those below:

10.1.0.256
1.2.3.
127.0.1-2.3

For IPv4 CIDR (Classless Inter-Domain Routing) I use this regex:

^(([0-9])|([1-9][0-9])|(1([0-9]{2}))|(2[0-4][0-9])|(25[0-5]))((\.(([0-9])|([1-9][0-9])|(1([0-9]{2}))|(2[0-4][0-9])|(25[0-5]))){3})\/(([0-9])|([12][0-9])|(3[0-2]))$

It is in this structure: ^(N)((\.(N)){3})\/M$ where N is the regex used to match number from 0 to 255, and M is the regex used to match number from 0 to 32.
This regex will match CIDR like below:

0.0.0.0/0
192.168.1.2/32

but not those below:

10.1.0.256/16
1.2.3./24
127.0.0.1/33

And for list of IPv4 CIDR like "10.0.0.0/16", "192.168.1.1/32" I use this regex:

^("(([0-9])|([1-9][0-9])|(1([0-9]{2}))|(2[0-4][0-9])|(25[0-5]))((\.(([0-9])|([1-9][0-9])|(1([0-9]{2}))|(2[0-4][0-9])|(25[0-5]))){3})\/(([0-9])|([12][0-9])|(3[0-2]))")((,([ ]*)("(([0-9])|([1-9][0-9])|(1([0-9]{2}))|(2[0-4][0-9])|(25[0-5]))((\.(([0-9])|([1-9][0-9])|(1([0-9]{2}))|(2[0-4][0-9])|(25[0-5]))){3})\/(([0-9])|([12][0-9])|(3[0-2]))"))*)$

It is in this structure: ^(“C”)((,([ ]*)(“C”))*)$ where C is the regex used to match CIDR (like 0.0.0.0/0).
This regex will match list of CIDR like below:

“10.0.0.0/16”,”192.168.1.2/32”, “1.2.3.4/32”

but not those below:

“10.0.0.0/16” 192.168.1.2/32 “1.2.3.4/32”

Maybe it might get shorter but for me it is easy to understand so fine by me.

Hope it helps!

Upvotes: 4

Martin Ml&#237;ch
Martin Ml&#237;ch

Reputation: 1

I saw very bad regexes in this page.. so i came with my own:

\b((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\b

Explanation:

num-group = (0-9|10-99|100-199|200-249|250-255)
<border> + { <num-group> + <dot-cahracter> }x3 + <num-group> + <border>

Here you can verify how it works here

Upvotes: 0

Jason Shaffner
Jason Shaffner

Reputation: 99

This one matches only valid IPs (no prepended 0's, but it will match octets from 0-255 regardless of their 'function' [ie reserved, private, etc]) and allows for inline matching, where there may be spaces before and/or after the IP, or when using CIDR notation.

grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)'

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< '10.0.1.2'
10.0.1.2

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< 'ip address 10.0.1.2'
ip address 10.0.1.2

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< 'ip address 10.0.1.2 255.255.255.255'
ip address 10.0.1.2 255.255.255.255

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< 'ip address 10.0.1.2/32'
ip address 10.0.1.2/32

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< 'ip address 10.0.1.2.32'
$

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< 'ip address10.0.1.2'
$

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< '10.0.1.256'
$

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< '0.0.0.0'
0.0.0.0

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< '255.255.255.255'
255.255.255.255

$ grep -E '(^| )((([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])($| |/)' <<< '255.255.255.256'
$

Of course, in cases where the IP is inline, you can use grep option "-o" and your preference of whitespace trimmer if you just want the whole IP and nothing but the IP.

For those of us using python, the equivalent is roughly:

>>> ipv4_regex = re.compile(r'(^| )((?:[1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:[1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])($| |/)')
>>> ipv4_regex.search('ip address 10.1.2.3/32')
<re.Match object; span=(10, 20), match=' 10.1.2.3/'>

If you're picky (lazy) like me, you probably would prefer to use grouping to get the whole IP and nothing but the IP, or the CIDR and nothing but the CIDR or some combination thereof. We can use (?P) syntax to name our groups for easier reference.

>>> ipv4_regex = re.compile(r'(?:^| )(?P<address>((?:[1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:[1-9]?\d|1\d{2}|2[0-4]\d|25[0-5]))(?P<slash>/)?(?(slash)(?P<cidr>[0-9]|[12][0-9]|3[0-2]))(?:$| )')
>>> match = ipv4_regex.search('ip address 10.0.1.2/32')
>>> match.group('address')
'10.0.1.2'
>>> match.group('cidr')
'32'
>>> "".join((match.group('address'), match.group('slash'), match.group('cidr')))
'10.0.1.2/32'

There's ways of not using just regex, of course. Here's some conditions that you could check (this one doesn't find inline, just validates the passed address is valid).

First check is that each char in the address is a digit or a '.'

Next checking that there are exactly 3 '.'

The next two checks check that each octet is between 0 and 255.

And the last check is that no octets are prepended with a '0'

def validate_ipv4_address(address):
    return all(re.match('\.|\d', c) for c in address) \
        and address.count('.') == 3 \
        and all(0 <= int(octet) <= 255 for octet in address.split('.')) \
        and all((len(bin(int(octet))) <= 10 for octet in address.split('.'))) \
        and all(len(octet) == 1 or d[0] != '0' for octet in address.split('.'))


>>> validate_ipv4_address('255.255.255.255')
True
>>> validate_ipv4_address('10.0.0.1')
True
>>> validate_ipv4_address('01.01.01.01')
False
>>> validate_ipv4_address('123.456.789.0')
False
>>> validate_ipv4_address('0.0.0.0')
True
>>> validate_ipv4_address('-1.0.0.0')
False
>>> validate_ipv4_address('1.1.1.')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in validate_ipv4_address
  File "<stdin>", line 4, in <genexpr>
ValueError: invalid literal for int() with base 10: ''
>>> validate_ipv4_address('.1.1.1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in validate_ipv4_address
  File "<stdin>", line 4, in <genexpr>
ValueError: invalid literal for int() with base 10: ''
>>> validate_ipv4_address('1..1.1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in validate_ipv4_address
  File "<stdin>", line 4, in <genexpr>
ValueError: invalid literal for int() with base 10: ''

(bitwise, each octet should be 8 bits or less, but each is prepended with '0b')

>>> bin(0)
'0b0'
>>> len(bin(0))
3
>>> bin(255)
'0b11111111'
>>> len(bin(256))
11

Upvotes: 0

Alex Harvey
Alex Harvey

Reputation: 15472

I think many people reading this post will be looking for simpler regular expressions, even if they match some technically invalid IP addresses. (And, as noted elsewhere, regex probably isn't the right tool for properly validating an IP address anyway.)

Remove ^ and, where applicable, replace $ with \b, if you don't want to match the beginning/end of the line.

Basic Regular Expression (BRE) (tested on GNU grep, GNU sed, and vim):

/^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$/

Extended Regular Expression (ERE):

/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/

or:

/^([0-9]+(\.|$)){4}/

Perl-compatible Regular Expression (PCRE) (tested on Perl 5.18):

/^\d+\.\d+\.\d+\.\d+$/

or:

/^(\d+(\.|$)){4}/

Ruby (tested on Ruby 2.1):

Although supposed to be PCRE, Ruby for whatever reason allowed this regex not allowed by Perl 5.18:

/^(\d+[\.$]){4}/

My tests for all these are online here.

Upvotes: 15

Shruti Lakkihal
Shruti Lakkihal

Reputation: 61

''' This code works for me, and is as simple as that.

Here I have taken the value of ip and I am trying to match it with regex.

ip="25.255.45.67"    

op=re.match('(\d+).(\d+).(\d+).(\d+)',ip)

if ((int(op.group(1))<=255) and (int(op.group(2))<=255) and int(op.group(3))<=255) and (int(op.group(4))<=255)):

print("valid ip")

else:

print("Not valid")

Above condition checks if the value exceeds 255 for all the 4 octets then it is not a valid. But before applying the condition we have to convert them into integer since the value is in a string.

group(0) prints the matched output, Whereas group(1) prints the first matched value and here it is "25" and so on. '''

Upvotes: 6

BabiBN
BabiBN

Reputation: 81

Easy way

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

Demo

Upvotes: 0

Dilip Paudel
Dilip Paudel

Reputation: 39

Following is the regex expression to validate the IP-Address.

^((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]?)$

Upvotes: 0

Kushagra Gupta
Kushagra Gupta

Reputation: 61

Above answers are valid but what if the ip address is not at the end of line and is in between text.. This regex will even work on that.

code: '\b((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\.)){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\b'

input text file:

ip address 0.0.0.0 asfasf
 sad sa 255.255.255.255 cvjnzx
zxckjzbxk  999.999.999.999 jshbczxcbx
sjaasbfj 192.168.0.1 asdkjaksb
oyo 123241.24121.1234.3423 yo
yo 0000.0000.0000.0000 y
aw1a.21asd2.21ad.21d2
yo 254.254.254.254 y0
172.24.1.210 asfjas
200.200.200.200
000.000.000.000
007.08.09.210
010.10.30.110

output text:

0.0.0.0
255.255.255.255
192.168.0.1
254.254.254.254
172.24.1.210
200.200.200.200

Upvotes: 5

Deepak_Mahalingam
Deepak_Mahalingam

Reputation: 454

ip address can be from 0.0.0.0 to 255.255.255.255

(((0|1)?[0-9][0-9]?|2[0-4][0-9]|25[0-5])[.]){3}((0|1)?[0-9][0-9]?|2[0-4][0-9]|25[0-5])$

(0|1)?[0-9][0-9]? - checking value from 0 to 199
2[0-4][0-9]- checking value from 200 to 249
25[0-5]- checking value from 250 to 255
[.] --> represent verify . character 
{3} --> will match exactly 3
$ --> end of string

Upvotes: 0

Related Questions