Reputation: 59
The following shell script works in Linux, but won't on Solaris,
#!/usr/bin/bash
while getopts ":s:" opt; do
case $opt in
s)
# Check IP against regex
if [[ "$OPTARG" =~ "\b(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]?)\b" ]]; then
IP=$OPTARG
else
echo "Invalid"
exit 1
fi
;;
esac
done
Linux:
GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu) Copyright (C) 2005 Free Software Foundation, Inc.
$ ./regextest.sh -s 10.2.4.3
$
$ ./regextest.sh -s 10.notaIP.10
Invalid
That is the expected result.
However on Solaris,
GNU bash, version 3.00.16(1)-release (sparc-sun-solaris2.10) Copyright (C) 2004 Free Software Foundation, Inc.
./regextest.sh -s 10.2.4.3
Invalid
GNU bash, version 3.2.51(1)-release (sparc-sun-solaris2.10) Copyright (C) 2007 Free Software Foundation, Inc.
./regextest.sh -s 10.2.4.3
Invalid
Thanks
Upvotes: 4
Views: 902
Reputation: 10169
There's a difference between RegEx implementations (GNU vs. POSIX).
POSIX doesn't understand \b
but GNU treats it as you would expect a word boundary.
Since you're testing a single IP at a time, try changing your expression from using word boundary \b
to using start of ^
and end of $
string/line, which are both recognized in most RegEx flavors.
"^(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]?)$"
Upvotes: 4
Reputation: 531215
Rather than wrestle with that monstrosity of a regular expression, just check each octet separately:
IFS=. read a b c d extra <<< "$OPTARG"
[[ -n $extra ]] && { echo "Too many octets"; exit 1; }
for octet in "$a" "$b" "$c" "$d"; do
[[ $octet =~ [[:digit:]]+ ]] &&
(( octet <= 255 )) || {
echo "Octet '$octet' must be a single byte"; exit 1
}
}
IP="$a.$b.$c.$d"
Possibly slower, sure, but argument checking shouldn't be a bottleneck in your program.
Upvotes: 2