36

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.

9
  • 4
    It will match 999.999.999.999 too.
    – cYrus
    Oct 24, 2010 at 12:11
  • 5
    So, you only want to grep IPv4 addresses, right?
    – Arjan
    Oct 24, 2010 at 12:51
  • 5
    Technically, IP addresses such as 192.1.4097 are valid and accepted by Linux glibc and Windows.
    – user1686
    Oct 24, 2010 at 14:49
  • 1
    Ah, I never knew! ping 2130706433, on OS X: PING 2130706433 (127.0.0.1): 56 data bytes.
    – Arjan
    Oct 24, 2010 at 15:15
  • 1
    @Arjan: 0x7f.1 and 0177.1
    – user1686
    Nov 7, 2010 at 10:23

13 Answers 13

61

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.

11
  • 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
    Oct 24, 2010 at 13:04
  • 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
    Oct 24, 2010 at 13:08
  • like this ? grep -E '\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b' /etc/hosts
    – jennifer
    Oct 24, 2010 at 13:14
  • 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
    Oct 25, 2010 at 16:21
  • 1
    Your regexp doesn't match 10.0.0.1 Sep 13, 2012 at 8:36
11

How's this:

perl -MRegexp::Common=net -ne '/($RE{net}{IPv4})/ and print "$1\n"' /etc/hosts
2
  • Nice! (This also returns 192.1.1.1.160 as 192.1.1.1, which I think is fine for the question asker.)
    – Arjan
    Oct 24, 2010 at 13:57
  • 2
    If 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 :-) . Sep 13, 2012 at 11:03
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!

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.

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;
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 )
4
  • What about 127.000.000.001 then? ;-)
    – Arjan
    Oct 24, 2010 at 15:20
  • As far as I know IPs doesn't have padding zeros.
    – cYrus
    Oct 24, 2010 at 15:22
  • 1
    Hmmm, 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
    Oct 24, 2010 at 15:23
  • 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
    Oct 24, 2010 at 15:33
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

2
  • 2
    welcome 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. Nov 17, 2015 at 10:40
  • 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
    Jul 28, 2017 at 20:38
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

1
  • This won't match 127.0.0.1 either. Aug 23, 2016 at 16:31
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.
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}'

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"
}
0

Old chain, but I needed a grep which would ALSO CATCH CIDR masks (8-32), so I use this:

grep -Eo "\b(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]\
|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\
([/]([8-9]|[12][0-9]|3[0-2]))?\b"

The above can be improved ;)

Now if mask is other than 8-32 but if the "IP-part" is still valid, grep returns the "IP-part".

-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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.