Regular expression in Bash to validate IP-address

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

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.


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