1

my target is to match exactly IP address with three octes , while the four IP octet must be valid octet - between <0 to 255>

For example I have the following IP's in file

$ more file    
192.9.200.10
192.9.200.100
192.9.200.1555
192.9.200.1
192.9.200.aaa
192.9.200.@
192.9.200.:
192.9.200
192.9.200.

I need to match the first three octets - 192.9.200 while four octet must be valid ( 0-255)

so finally - expects result should be:

192.9.200.10
192.9.200.100
192.9.200.1

the basic syntax should be as the following:

IP_ADDRESS_THREE_OCTETS=192.9.200
cat file | grep -x $IP_ADDRESS_THREE_OCTETS.[  grep‏ Regular Expression syntax ]

Please advice how to write the right "grep regular Expression" in the four octets in order to match the three octets , while the four octets must be valid?

Chris Seymour
  • 83,387
  • 30
  • 160
  • 202

4 Answers4

3

You'd need to use some high-level tools to convert the text to a regex pattern, so you might as well use just that.

perl -ne'
    BEGIN { $base = shift(@ARGV); }
    print if /^\Q$base\E\.([0-9]+)$/ && 0 <= $1 && $1 <= 255;
' "$IP_ADDRESS_THREE_OCTETS" file

If hardcoding the base is acceptable, that reduces to:

perl -ne'print if /^192\.9\.200\.([0-9]+)$/ && 0 <= $1 && $1 <= 255' file

Both of these snippets also accept input from STDIN.


For a full IP address:

perl -ne'
    BEGIN { $ip = shift(@ARGV); }
    print if /^\Q$ip\E$/;
' 1.2.3.4 file

or

perl -nle'
    BEGIN { $ip = shift(@ARGV); }
    print if $_ eq $ip;
' 1.2.3.4 file
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • hi I am very like your answer with perl line liner especially the “Q and E” that replace the backslash “\” but one more question can you give another example from your answer – how to match exactly IP address with four octets , the solution of perl save the option to set “\” before the “.” –  Feb 22 '13 at 12:16
  • @Eytan, Added exact IP address solution to answer as requested. – ikegami Feb 22 '13 at 13:04
  • @Eytan, By the way, I split the code across multiple lines for readability, but it also works if you put it all one one line. – ikegami Feb 22 '13 at 13:05
2

Regexp is not good for comparing numbers, I'd do this with awk:

$ awk -F. '$1==192 && $2==9 && $3==200 && $4>=0 && $4<=255 && NF==4' file
192.9.200.10
192.9.200.100
192.9.200.1

If you really want to use grep you need the -E flag for extended regexp or use egrep because you need alternation:

$ grep -Ex '192\.9\.200\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])' file
192.9.200.10
192.9.200.100
192.9.200.1

$ IP=192\.9\.200\.

$ grep -Ex "$IP(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])" file

Note: You must escaped . to mean a literal period.

Chris Seymour
  • 83,387
  • 30
  • 160
  • 202
2
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])$'

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

Baby Groot
  • 4,637
  • 39
  • 52
  • 71
Thomas
  • 21
  • 1
0

If you really want to be certain that what you have is a valid IPv4 address, you can always check the return value of inet_aton() (part of the Socket core module).

fenway
  • 416
  • 2
  • 8