5

In my Python script i have a regular expression for searching IP-addresses like 0.0.0.0-255.255.255.255 in a file, it looks like this:

[1-2]{0,1}[0-9]{0,1}[0-9]{1}\.[1-2]{0,1}[0-9]{0,1}[0-9]{1}\.[1-2]{0,1}[0-9]{0,1}[0-9]{1}\.[1-2]{0,1}[0-9]{0,1}[0-9]{1}

Now i need to have the same in a Bash script. So i changed it like this:

[1-2]\{0,1\}[0-9]\{0,1\}[0-9]\{1\}\.[1-2]\{0,1\}[0-9]\{0,1\}[0-9]\{1\}\.[1-2]\{0,1\}[0-9]\{0,1\}[0-9]\{1\}\.[1-2]\{0,1\}[0-9]\{0,1\}[0-9]\{1\}

Works almost fine but for some reason it filters addresses like "1000.0.0", "2323.23.23.2323" and so on. Why is that so.

1
8

Tried to shorten the regexp, here is the result:

#!/bin/bash

rx='([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])'

for ip in 08.08.08.08 3.3.3.3 11.11.11.11 \
      111.123.11.99 \
      222.2.3.4 999.88.9.9 \
      255.255.255.255 255.0.3.3 0.256.0.222; do

   if [[ $ip =~ ^$rx\.$rx\.$rx\.$rx$ ]]; then
      echo "valid:     "$ip
   else
      echo "not valid: "$ip
   fi
done
5
  • Note that it says 08.08.08.08 is valid. Jan 31 '14 at 12:58
  • Do you mean that leading zeros are not allowed?
    – user55518
    Jan 31 '14 at 13:01
  • 1
    I mean that leading zero usually means octal in IP address, and 08 is not a valid octal. In firefox for instance, if you enter http://010.010.010.010, you query 8.8.8.8, and if you query http://08.08.08.08, firefox tries to resolve it as a hostname as it's not a valid IP address. Jan 31 '14 at 13:03
  • That's new to me, could you check again?
    – user55518
    Jan 31 '14 at 13:15
  • Looks alright now. Further reading in the man pages of inet_addr (BSD/POSIX syntax very widespread), inet_pton (only decimal only quad, up to 3 digits allowed per component). gethostbyname and getaddrinfo usually support the same as inet_addr. Then, you can have everything in between. If checking the sanity of input, I think your latest solution is the safest. 010.010.010.010 is valid for most tools but do not necessarily mean the same for all, so it's better to reject it. Jan 31 '14 at 13:25
4

The python regexp is using the extended regular expression syntax which comes from the egrep command in the 70s (though the {...} part was added later, and actually in grep before egrep).

POSIX have consolidated the grep and egrep commands (egrep is now grep -E) in the 90s and standardized the {x,y} operator (which wasn't available in the earlier egreps).

So now, you should be able to use grep -E 'that-regexp' with all modern grep implementations.

Note that your regexp would allow 299.299.299.299 and the {1}s are redundant. {0,1} can be shortened to ?.

Note that grep find lines that match the regexp, that is lines that contain a string that match the regexp anywhere. Use ^ and $ to anchor, or use the -x option to grep.

4

I think this should cover it

$ octet="(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])"

Or to avoid zeros on the left:

$ octet="(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])"  

You can then make use of $octet:

$ ip4="^$octet\\.$octet\\.$octet\\.$octet$"
$ echo $ip4
^(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])$
$ [[ 123.234.12.34 =~ $ip4 ]] && echo y || echo n
y
$ [[ 123.234.12.345 =~ $ip4 ]] && echo y || echo n
n
1
  • @p.glez: your edit is not necessary. The original "octet" regex will match all of "007", "07" and "7" due to the use of the ? quantifier. Your regex cannot match the valid IP address 127.001.001.001 Feb 23 '15 at 1:02
1

you can integrate this function with your code to validate IP Address. If you can share your current code, I can be more specific to the problem.

function validateIP()
 {
         local ip=$1
         local stat=1
         if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
                OIFS=$IFS
                IFS='.'
                ip=($ip)
                IFS=$OIFS
                [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
                && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
                stat=$?
        fi
        return $stat
}

echo "Enter IP Address"
read ip
validateIP $ip

if [[ $? -ne 0 ]];then
  echo "Invalid IP Address ($ip)"
else
  echo "$ip is a Perfect IP Address"
fi
6
  • This returns false for valid IP addresses, for example, 127.1 is a valid IP address.
    – Chris Down
    Jan 31 '14 at 12:27
  • It also returns false for 0111.0111.0111.0111 or 08.08.08.08 (that one with a value too great for base error) Jan 31 '14 at 12:49
  • BTW, depending on who you're asking, 08.08.08.08 is valid or not, and 010.010.010.010 means 8.8.8.8 (most common) or 10.10.10.10 Jan 31 '14 at 12:57
  • @Stephane - Thanks for your attention, I think this 08.08.08.08 is considered as an Octal value by the server because 0 is defines Octal number, so server is ignoring that value.
    – 124
    Jan 31 '14 at 13:04
  • @Stephane Chazelas I understand why most implementations interpret leading zeros as octal but RFC 1123 specifically says an all-numeric a.b.c.d is dotted decimal. 010 should be decimal 10 not decimal 8.
    – doneal24
    Jan 31 '14 at 14:18

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.