LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - General (http://www.linuxquestions.org/questions/linux-general-1/)
-   -   Using sed to match an IP address. (http://www.linuxquestions.org/questions/linux-general-1/using-sed-to-match-an-ip-address-921858/)

mattst 01-03-2012 04:36 PM

Using sed to match an IP address.
 
I have a script which gets the IP address from a web site (Eg. http://checkip.dyndns.org among others) and strips everything (Eg. "Your IP is:") leaving just the IP - that part works fine. I have a problem with error checking that a valid IP address was returned.

What I've been trying to do is run a sed command that matches the following:

A 0, 1, or 2, followed by 0-9 appearing either 0, 1, or 2 times, followed by a '.'. Then repeating that 3 times to match a 4 number IP address. Perhaps not perfect logic as that would validate 0.0.0.0 - but I can be fairly sure that if the getting the IP from a web site fails then it's not going to leave me with anything approximating an IP which might cause my error check to give a false positive.

Here's an example of my (not working) sed command:

Code:

echo "255.1.22.33" | sed "s/^[0-2]{1,1}[0-9]{0,2}\.[0-2]{1,1}[0-9]{0,2}\.[0-2]{1,1}[0-9]{0,2}\.[0-2]{1,1}[0-9]{0,2}$//g"
My test is to run the sed command on what should be the IP with the sed replace section empty (as above), therefore if sed provides an empty string I know that the IP was valid.

The problem is that the code above just returns the whole IP given in the echo. I've been pulling my hair out trying to fix it but can't work it out at all.

Any help appreciated. Thanks.

Wellesly 01-03-2012 07:18 PM

The first problem is that you probably need to escape your braces with a backslash: '\{1,1\}'. I am not sure that this is true in all implementations, locations, and other such variations, so you should test it with something simple.

The second problem is that the first digit of '33' does not fall into the range [0-9], but your regular expression is expecting this. Here is a technique for finding numbers in a range.

mattst 01-04-2012 04:18 AM

Thanks Wellesly.

Quote:

Originally Posted by Wellesly (Post 4565212)
The first problem is that you probably need to escape your braces with a backslash: '\{1,1\}'. I am not sure that this is true in all implementations, locations, and other such variations, so you should test it with something simple.

Yes that has fixed it - I hadn't realized that could be a problem.

Quote:

Originally Posted by Wellesly (Post 4565212)
The second problem is that the first digit of '33' does not fall into the range [0-9], but your regular expression is expecting this. Here is a technique for finding numbers in a range.

Actually the '33' was just a mistake in my post here (and you meant the range [0-2]). The actual code was using my real IP address and at the point of posting I changed it stupidly to an invalid IP. Thanks for the number range link, I'll try that approach instead.

Thanks again and happy new year.

EDIT: Of course my logic was all wrong anyway and I suspect a complete brain meltdown due to New Year excess. 33 is valid in an IP, only 333 would not be, an IP only need begin with 0,1,2 if it's 3 digits in length, if it's 1 or 2 digits in length it can begin with anything. Oops. END EDIT

Cedrik 01-04-2012 08:00 AM

You could also do simple check by spliting IP into 4 numbers and check if each number is > 255

Code:

echo "255.1.22.0.56" | perl -F'\.' -pane '$_= (scalar @F != 4 or grep {$_>255}@F) ? "IP not ok\n":"IP ok\n"'
(edit)
Sorry, just realized it was a sed question :(

trey85stang 01-04-2012 09:48 AM

Sed can do that.. but perl awk, or a bash loop would be a better choice for veriving an ip address as valid...

here is an awk one i use as a function in my scripts...

Code:

awk --posix '
  BEGIN { FS="." }
    { if(NF != "4") {
      ret=1
    }
    if($1 !~ /[[:digit:]]{1,3}/ || $2 !~ /[[:digit:]]{1,3}/ || $3 !~ /[[:digit:]]{1,3}/ || $3 !~ /[[:digit:]]{1,3}/) {
      ret=2
    }
    if($1 > 255 || $2 > 255 || $3 > 255 || $4 > 255) {
      ret=3
    }
  } END {
    exit ret
  }'

Id like to see what you come up with in sed if you get it working though.

Wellesly 01-04-2012 02:51 PM

Quote:

Originally Posted by mattst (Post 4565590)
(and you meant the range [0-2]).

Well—that’s embarassing.

r900 10-15-2012 06:14 PM

i guess it comes a little late for solving your problem, but just in case someone else is looking for it, here's a solution a friend of mine and me came up with:

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


the "\?" needs gnu sed, and it's a little, ... , unreadable - but here you are ;)


All times are GMT -5. The time now is 07:34 AM.