Ajain
Ajain

Reputation: 31

Bash script - not able to validate ip

Please help me to understand the syntax below:

#!/bin/bash
read -p "enter your value"  ip
if [[ $ip =~ ^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ ]]
then
    echo "valid"
else
    echo "invalid"
fi

With input 923.234214.23, the result is valid. With 923.3444.2123, it is invalid.

How can I solve this?

Upvotes: 0

Views: 339

Answers (4)

Ajain
Ajain

Reputation: 31

Thanks for reply finally i found a solution

if [[ $ip =~ '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' ]]

i was not using single quote.

Upvotes: 0

cerkiewny
cerkiewny

Reputation: 2851

I think you are using . instead of \.

the following script should do what you want:

#!/bin/bash
read -p "enter your value" ip
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]
   then
     echo "valid"
   else
     echo "invalid"
fi

If you want more advanced script actually checking the scope of the numbers given you could look into this linux journal article.

Upvotes: 3

Sylvain Leroux
Sylvain Leroux

Reputation: 52000

And for a real answer now, if you want to check for IPv4 addresses using only bash, you have to use a slightly more complex regex. I use an intermediate variable here to keep the things understandable:

BYTE='((0*1?[0-9]?[0-9])|(2[0-4][0-9])|(25[0-5]))'
#      ^^^^^^^^^^^^^^^^^                           matches 0-199 (with optional leading zeros
#                        ^^^^^^^^^^^^^             matches 200-249
#                                      ^^^^^^^^^   matches 250-255
if [[ $ip =~ ^$BYTE\.$BYTE\.$BYTE\.$BYTE$ ]]
then
    # ...
else
    # ...
fi

Upvotes: 3

Sylvain Leroux
Sylvain Leroux

Reputation: 52000

This is more a comment than a real answer but...

# _your_ regex:
sh$ [[ 923.34442.123 =~ ^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ ]] && echo ok || echo notok
ok

# regex using backslash:
sh$ [[ 23.34442.123 =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] && echo ok || echo notok
notok

As this has already been explained, the key point is the use of the backslash (\). The dot (.) alone will match any single character. The [0-9]{1,3} part means "match any sequence of 1 to 3 digit".

So, broadly speaking, your regex would match any string having 4 sequences of 1 to 3 digits separated by any char:

9  2  3  .  3  4  4  4  2  .  1  2  3

d  d  d  a  d  d  d  a  d  a  d  d  d
i  i  i  n  i  i  i  n  i  n  i  i  i
g  g  g  y  g  g  g  y  g  y  g  g  g
i  i  i  c  i  i  i  c  i  c  i  i  i
t  t  t  h  t  t  t  h  t  h  t  t  t
         a           a     a
         r           r     r

It might be surprising at first, but it matches...


As a side note, even the "backslash-dot regex" will accept non valid IPv4 addresses: for example 923.34.42.123 would match, but is obviously incorrect. So for fun here is an awk based filter (and its test set) to remove invalid IPv4 addresses from a listing. Feel free to adapt to your needs (or ignore it completely;)

sh$ BYTE='[0-2]?[0-9]?[0-9]' # Might even be BYTE='0*[0-2]?[0-9]?[0-9]'
sh$ cat << EOF | awk -v FS='.' "/^$BYTE\.$BYTE\.$BYTE\.$BYTE$/"' {
                                   if (($1<= 255)&&($2<=255)&&($3<=255)&&($4<=255))
                                      print $0 }'              
4.2.2.2
a.b.c.d
192.168.1.1
0.0.0.0
255.255.255.255
255.255.255.256
192.168.0.1
192.168.0
1234.123.123.123
EOF

And here is the result:

4.2.2.2
192.168.1.1
0.0.0.0
255.255.255.255
192.168.0.1

Upvotes: 1

Related Questions