1

I'm making a script that validate an IP address. I do this:

read pool checkIp() { 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 } checkIp $pool if [ $? -eq 0 ] then echo "valid" else echo "invalid" fi 

The problem is that now the requirement is to valid that from the 2nd octet the input can contain the wildcard "*" (i think is better to use CIDR notation but is not the case), and now i can't use -le because if there is not a number, it fails.

I'd tried some forms but all conversions fails.

3
  • Not really into network addressing. Is “1.2.*.4” valid (my answer allows it), or as soon a “” is encountered the remaining pieces have to also be “”s? Commented Jan 30, 2013 at 14:23
  • The remaining spaces should be "*"... Commented Jan 30, 2013 at 15:18
  • Note that allowing 010.010.010.010 could cause confusion as most applications and library functions (gethostbyname, inet_addr...) consider it the same as 8.8.8.8 while some other the same as 10.10.10.10 (inet_pton). Commented Jan 30, 2013 at 15:27

2 Answers 2

3

With a little additional rewrite. (As you use Bash-specific regular expression, just populate the BASH_REMATCH array instead of manipulating a word splitting.)

checkIp() { local ip="$1" if [[ "$ip" =~ ^([0-9]{1,3})\.([0-9]{1,3}|\*)\.([0-9]{1,3}|\*)\.([0-9]{1,3}|\*)$ ]]; then for ((i=1;i<=4;i++)); do [[ "${BASH_REMATCH[i]}" == '*' || "${BASH_REMATCH[i]}" -le 255 ]] || return 1 done return 0 fi return 1 } 

Update according to owner's comment to disallow numbers after “*”:

checkIp() { local ip="$1" local asterisk='' if [[ "$ip" =~ ^([0-9]{1,3})\.([0-9]{1,3}|\*)\.([0-9]{1,3}|\*)\.([0-9]{1,3}|\*)$ ]]; then for ((i=1;i<=4;i++)); do [[ "${BASH_REMATCH[i]}" == '*' || ( ! "$asterisk" && "${BASH_REMATCH[i]}" -le 255 ) ]] || return 1 [[ "${BASH_REMATCH[i]}" == '*' ]] && asterisk='1' done return 0 fi return 1 } 
0
2

For the record, with zsh, you could write it:

[[ $ip = <0-255>.(<0-255>|"*").(<0-255>|"*").(<0-255>|"*") ]] 

Note that it allows 000001.0000255.*.0, but not 0377.1.1.1 (even though 0377 as taken as an octal number is within range), because it only considers decimal numbers.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.