4

以下 shell 脚本适用于 Linux,但不适用于 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,版本 3.2.25(1)-release (x86_64-redhat-linux-gnu) 版权所有 (C) 2005 Free Software Foundation, Inc.

$ ./regextest.sh -s 10.2.4.3
$


$ ./regextest.sh -s 10.notaIP.10
Invalid

这是预期的结果。

但是在 Solaris 上,

GNU bash,版本 3.00.16(1)-release (sparc-sun-solaris2.10) 版权所有 (C) 2004 Free Software Foundation, Inc.

./regextest.sh -s 10.2.4.3
Invalid

GNU bash,版本 3.2.51(1)-release (sparc-sun-solaris2.10) 版权所有 (C) 2007 Free Software Foundation, Inc.

./regextest.sh -s 10.2.4.3
Invalid

谢谢

4

2 回答 2

4

RegEx 实现(GNU 与 POSIX)之间存在差异。
POSIX 不理解\b,但 GNU 将其视为您期望的单词边界

由于您一次测试一个 IP,因此请尝试将表达式从使用单词边界 \b更改为使用字符串/行的开头 ^结尾 ,这在大多数 RegEx 风格中都可以识别。 $

"^(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]?)$"
于 2013-05-23T16:56:49.063 回答
2

而不是与正则表达式的怪物搏斗,只需分别检查每个八位字节:

 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"

当然,可能会更慢,但参数检查不应该成为程序的瓶颈。

于 2013-05-23T16:56:39.793 回答