【问题标题】:Validate an ip in dash (not bash)在破折号中验证 ip(不是 bash)
【发布时间】:2012-03-05 18:19:04
【问题描述】:

我正在尝试在破折号脚本中验证 IP 地址。我找到了很多方法来实现与 bash 相同的功能,例如 linuxjournal

基本上是用这个进行比较:

if [[ $ip =~ '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' ]]; then
  do something
fi

有什么办法可以用破折号来达到同样的效果吗?

更新:这是完成我需要的最终脚本:

#In case RANGE is a network range (cidr notation) it's splitted to every ip from 
# that range, otherwise we just keep the ip
if echo $RANGE | grep -E -q '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}$'; then
    IPS=`prips $RANGE -e ...0,255`
    if [ "$?" != "0" ] ; then
        echo "ERROR: Not a valid network range!"
        exit 1
    fi
elif echo $RANGE | grep -E -q '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'; then
    IPS="$RANGE"
else
    echo "$RANGE no is not a valid IP address or network range"
    exit 1
fi

【问题讨论】:

  • IP 地址只是一个 32 位数字。您要求使用点分四进制表示法,但请记住十进制和十六进制表示法同样有效。 0x1020304169090601.2.3.4 相同。
  • 我只需要验证人为错误,除了我和我的同事之外没有人会使用这个脚本,所以我可以选择一个符号并坚持下去。
  • 关于你的最终正则表达式,你也可以用更短的形式来表示它:^([0-9]{1,3}\.){3}[0-9]{1,3}\/[0-9]{1,2}$
  • 您使用了许多不同的外部命令,而仅使用 dash 内置命令就可以做到这一点。 (如果您对如何操作感到好奇,请参阅下面的回复。)

标签: shell sh dash-shell


【解决方案1】:

这是一个小的dash shell 函数它不使用任何外部命令并检查 IPv4 地址是否有效。如果地址格式正确,则返回 true,否则返回 false。

我试图解释我的 cmets 中的魔力。

valid_ip() {
    local IP="$1" IFS="." PART           # make vars local, get arg, set $IFS
    set -- $IP                           # split on $IFS, set $1, $2 etc.
    [ "$#" != 4 ] && return 1            # BAD: if not 4 parts
    for PART; do                         # loop over $1, $2 etc.
        case "$PART" in
            *[!0-9]*) return 1           #   BAD: if $PART contains non-digit
        esac
        [ "$PART" -gt 255 ] && return 1  #   BAD: if $PART > 255
    done
    return 0                             # GOOD: nothing bad found
}

使用此功能,您可以测试您的 IP 地址,例如如果 IP 地址无效,则中止脚本:

if valid_ip "$IP"; then
    echo "ERROR: IP address '$IP' is invalid" >&2
    exit 4
fi

【讨论】:

    【解决方案2】:

    您可以构建case 语句,尽管它比正则表达式更冗长。另一方面,您可以避免产生任何外部进程,并且它可能更易于阅读和维护以启动。

    if case $ip in
        # Invalid if it contains any character other than number or dot
        # Invalid if it contains more than three dots
        # Invalid if it contains two adjacent dots
        # Invalid if it begins with a non-number
        # Invalid if it ends with a non-number
        *[!.0-9]* | *.*.*.*.* | *..* | [!0-9]* | *[!0-9] ) false ;;
        # Invalid if it contains a number bigger than 255:
        #  256-259 or 260-299 or 300-999 or four adjacent digits
        *25[6-9]* | *2[6-9][0-9]* | *[3-9][0-9][0-9]* | *[0-9][0-9][0-9][0-9]* ) false;;
        # Verify that it contains three dots
        *.*.*.* ) true ;;
        # Failing that, invalid after all (too few dots)
        *) false ;;
    esac; then
        echo "$ip" is valid
    fi
    

    注意case 语句(返回真或假)作为if 语句中的条件的时髦用法。

    这比正则表达式稍微严格,因为它要求每个八位字节小于 256。

    【讨论】:

    • 我不想调试这样的函数...:/
    【解决方案3】:

    假设您对验证字符串感到满意:

    $ s='[0-9]\{1,3\}' $ 回声 $ip | grep > /dev/null "^$s\.$s\.$s\.$s$" && echo $ip 有效

    请注意,这接受无效的 IP 地址,例如 876.3.4.5

    要验证一个ip,用正则表达式真的很不方便。一个相对容易的事情是:

    国际金融服务公司=。读取 a b c d /dev/null ) 然后 echo $ip 有效 菲

    【讨论】:

    • 太好了,唯一的问题是我需要 -E 标志来评估正则表达式(或使用 egrep)非常感谢
    • 只有在使用 s='[0-9]{1,3}' 时才需要扩展正则表达式。如果你转义括号,基本的正则表达式应该可以工作。 (啊,你在我编辑之前发表了评论......)
    • 另外,重定向的东西有点奇怪。只需改用egrep -q "regex"
    • @ghoti 出于可移植性的原因,我一直避免使用 -q,但刚刚发现它是在 Open Group 规范中指定的,它可能足够便携!
    • @ghoti 另一方面, grep -q 可能被认为是臃肿:harmful.cat-v.org/cat-v
    猜你喜欢
    • 2016-09-18
    • 2012-05-10
    • 1970-01-01
    • 2017-01-18
    • 1970-01-01
    • 2016-06-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多