What regular expression can I use to match an IP address?

36

16

With the following grep syntax I want to match all IP address in a file (from a ksh script)

  grep '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' file

The problem: It also matches words (IP) that have more then 4 octets:

1.1.1.1.1 

or

192.1.1.1.160

How can I match a valid IP and only IP addresses with 4 octets? I can also use Perl – a one line syntax solution, if grep doesn't work.

jennifer

Posted 2010-10-24T12:00:49.097

Reputation: 897

Have a look at my answer in unix stackexchange: https://unix.stackexchange.com/a/389565/249079

– Ganapathy – 2017-09-29T05:35:23.403

4It will match 999.999.999.999 too. – cYrus – 2010-10-24T12:11:04.247

5

So, you only want to grep IPv4 addresses, right?

– Arjan – 2010-10-24T12:51:55.750

And as for you 192.1.1.1.160 example: would you expect 192.1.1.1 or 1.1.1.160 or no match at all? – Arjan – 2010-10-24T12:54:56.580

about 192.1.1.1 and 1.1.1.160 they valid IP I accept – jennifer – 2010-10-24T12:56:37.657

Errr? So, if the input is 192.1.1.1.160 then you just want 192.1.1.1 in the output? Then you don't have a problem (except for matching 999.999.999.999 an so on too), but just need the -o command line option to only print the actual matches, not the full lines?

– Arjan – 2010-10-24T13:04:24.103

5Technically, IP addresses such as 192.1.4097 are valid and accepted by Linux glibc and Windows. – user1686 – 2010-10-24T14:49:35.107

1

Ah, I never knew! ping 2130706433, on OS X: PING 2130706433 (127.0.0.1): 56 data bytes.

– Arjan – 2010-10-24T15:15:59.207

1@Arjan: 0x7f.1 and 0177.1 – user1686 – 2010-11-07T10:23:14.047

Answers

57

try this:

grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' /etc/hosts

which matches all expressions from 0.0.0.0 to 999.999.999.999

with

grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' /etc/hosts

you will get IP addresses only

note:
on solaris probably egrep will do the job.

udo

Posted 2010-10-24T12:00:49.097

Reputation: 7 661

In my head this would be confusing to write but your answer is actually really easy to understand now that I see the syntax of the regex – Kolob Canyon – 2016-09-15T20:12:30.837

I try the grep '\b\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}\b' /etc/hosts but I dont get anything -:( – jennifer – 2010-10-24T13:04:36.053

1@jennifer, you'll need to enable extended regular expressions: grep -E <pattern> <file> (or, to just print the matches: grep -Eo <pattern> <file> – Arjan – 2010-10-24T13:08:02.063

like this ? grep -E '\b\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}\b' /etc/hosts – jennifer – 2010-10-24T13:14:06.273

I updated my answer -> this should work now – udo – 2010-10-24T13:33:24.830

the problem is that -E isnt valid flag in solaris? -:( – jennifer – 2010-10-24T13:39:27.777

add a "solaris" tag to your question. not sure how to tweak this on solaris... – udo – 2010-10-24T13:42:32.040

try egrep on solaris ;) not sure if it works, but it should. let me know – udo – 2010-10-24T13:44:06.343

@jennifer, that's info that should have been in your question... In the end, the trick is the -o, like I already commented earlier. The regex above is not different from the one in your question, but without the -o all matching lines are printed, even if only part of that line is matched. (To use the regex from this answer without the -E you'll just need \{1,3\} instead of {1,3}.) – Arjan – 2010-10-24T13:44:41.480

3@udo: Well this matches 1.1.1.1.1 but it hides the last .1 from the output, I can't see how it can help. – cYrus – 2010-10-25T16:21:59.087

1Your regexp doesn't match 10.0.0.1 – Stefan Seidel – 2012-09-13T08:36:20.960

@Stefan Seidel: thanks -> updated the answer – udo – 2012-09-13T12:46:49.290

10

How's this:

perl -MRegexp::Common=net -ne '/($RE{net}{IPv4})/ and print "$1\n"' /etc/hosts

Joe Casadonte

Posted 2010-10-24T12:00:49.097

Reputation: 3 945

Nice! (This also returns 192.1.1.1.160 as 192.1.1.1, which I think is fine for the question asker.) – Arjan – 2010-10-24T13:57:51.247

2If conformant IP addresses are really wanted, this is the only type of solution that has any chance of being close to complete. When I saw the question, I just thought "I won't touch that with a ten-foot standard regexp pole". Caveats, caveats everywhere :-) . – Daniel Andersson – 2012-09-13T11:03:15.497

5

The

-w / --word-regexp 

flag to grep makes it only match on word boundaries, meaning that your match must either be surrounded by whitespace or begin / end at the beginning / end of the line!

Dominik George

Posted 2010-10-24T12:00:49.097

Reputation: 51

5

if [ ` echo $ip | '^((25[0-5]|2[0-4][0-9]|[01]?[1-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[1-9][0-9]?)$'  | grep -o "\." | wc -l` -eq 1 ];
then ipv4=true;
else 
ipv4=false;

Arnaud B.

Posted 2010-10-24T12:00:49.097

Reputation: 51

5

To only find matches with 4 octets exactly (excluding things like 1.1.1.1.1) use this:

grep -P '(?<=[^0-9.]|^)[1-9][0-9]{0,2}(\.([0-9]{0,3})){3}(?=[^0-9.]|$)'

It should never detect non-IP-addresses. The expression could be more complex to verify more things but this should work for most cases. It will not match a preceding 0 since 010.1.12.1 is not a common way to write IP addresses.

Stefan Seidel

Posted 2010-10-24T12:00:49.097

Reputation: 8 812

3

A little tricky, but it should work:

( X='\([0-9]\{1,2\}\|1[0-9]\{2\}\|2[0-4][0-9]\|25[0-5]\)' ; grep "\([^\.]\|^\)$X\.$X\.$X\.$X\([^\.]\|$\)" file )

cYrus

Posted 2010-10-24T12:00:49.097

Reputation: 18 102

What about 127.000.000.001 then? ;-) – Arjan – 2010-10-24T15:20:09.063

As far as I know IPs doesn't have padding zeros. – cYrus – 2010-10-24T15:22:04.683

1Hmmm, ping 127.000.000.001 surely works on my Mac. But then: I just learned that even ping 2130706433 yields the very same result. :-) Oops, ping 00127.00000.00000.00001 translates to 87.0.0.1. Odd... Or octal maybe? Yes, octal for sure, so you're right about leading zeroes I guess. – Arjan – 2010-10-24T15:23:42.867

Yes, 00127 (octal) = 87 (decimal). Surely they're all valid IPs, but I guess that's not the standard way to represent them. Anyway that's not requested by the asker. – cYrus – 2010-10-24T15:33:34.220

1

A shorter version of the long regex:

egrep '([1-2]?[0-9]{0,2}\.){3,3}[1-2]?[0-9]{0,2}' 

Please use grep -E or egrep as suitable to your OS version

Suhail

Posted 2010-10-24T12:00:49.097

Reputation: 11

2welcome at superuser. This question already has several good answers. To help people understanding differences between them, please edit your answer and explain what makes it better / different from the other ones. – Máté Juhász – 2015-11-17T10:40:34.743

this expression does not take into account such legal ips as 8.8.8.8 echo "8.8.8.8" | grep -Eo '([1-2][0-9]{0,2}\.){3,3}[1-2][0-9]{0,2}' => no result – anneb – 2017-07-28T20:38:01.907

0

grep -Eo '([0-9]{1,3}.?){4}'

Example : curl http://korben.info/ip | grep "IP visible depuis mon serveur" | grep -Eo '([0-9]{1,3}.?){4}'

user2357585

Posted 2010-10-24T12:00:49.097

Reputation: 101

0

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

Modified version of Arnaud B.'s answer.

This expression will not match IP addresses with leading 0s. e.g., it won't match 192.168.1.01 This expression will not match IP addresses with more than 4 octets. e.g., it won't match 192.168.1.2.3

Thomas

Posted 2010-10-24T12:00:49.097

Reputation: 1

This won't match 127.0.0.1 either. – Chris Charabaruk – 2016-08-23T16:31:13.853

0

Regular expression for matching an ip address in TCL

set a "192.168.10.25"

if {[regexp
{^(([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])$} $a]} 
{
    puts "yes"
}

abhilash.malla

Posted 2010-10-24T12:00:49.097

Reputation: 1

0

I'm using egrep "^([0-9]{1,3}\.){3}[0-9]{1,3}" /etc/hosts to match IP adresses at the beginning of a line. It can also be used without the ^ to allow white spaces or other chars before the IP address.

[0-9]{1,3} --> this matches a number between 1 and 999.
\. --> this is to add the dot.
([0-9]{1,3}\.){3} --> get a number with a dot 3 times.
[0-9]{1,3} --> finally add the fourth number.

Falk

Posted 2010-10-24T12:00:49.097

Reputation: 299

-1

Here is what worked for me for ksh and ksh93 in AIX:

ip=

[[ $ip == [0-9]@(""|[0-9])@(""|[0-9]).[0-9]@(""|[0-9])@(""|[0-9]).[0-9]@(""|[0-9])@(""|[0-9]).[0-9]@(""|[0-9])@(""|[0-9]) ]] && echo OK || echo NOK The above can be modified in order to "filter" the provided IP to whatever pattern is desired.

Niko

Posted 2010-10-24T12:00:49.097

Reputation: 1