在 Bash 脚本中验证 IP 地址

作者:Mitch Frazier

我最近写了关于使用 bash 数组bash 正则表达式 的文章,所以这里有一个更有用的例子,可以使用它们来测试 IP 地址的有效性。

为了强调显而易见的事实:IP 地址是 32 位的值,写成四个数字(IP 地址的单个字节),用点(句点)分隔。 这四个数字中的每一个的有效范围是 0 到 255。

以下 bash 脚本包含一个 bash 函数,如果传递给它一个有效的 IP 地址,则返回 true;否则返回 false。 在 bash 中,true 意味着它以零状态退出,任何其他状态都是 false。 命令/函数的状态存储在 bash 变量 "$?" 中。

#!/bin/bash

# Test an IP address for validity:
# Usage:
#      valid_ip IP_ADDRESS
#      if [[ $? -eq 0 ]]; then echo good; else echo bad; fi
#   OR
#      if valid_ip IP_ADDRESS; then echo good; else echo bad; fi
#
function valid_ip()
{
    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
}

# If run directly, execute some tests.
if [[ "$(basename $0 .sh)" == 'valid_ip' ]]; then
    ips='
        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
        '
    for ip in $ips
    do
        if valid_ip $ip; then stat='good'; else stat='bad'; fi
        printf "%-20s: %s\n" "$ip" "$stat"
    done
fi

如果您将此脚本保存为 "valid_ip.sh",然后直接运行它,它将运行一些测试并打印结果

  # sh valid_ip.sh
  4.2.2.2             : good
  a.b.c.d             : bad
  192.168.1.1         : good
  0.0.0.0             : good
  255.255.255.255     : good
  255.255.255.256     : bad
  192.168.0.1         : good
  192.168.0           : bad
  1234.123.123.123    : bad

在函数中valid_ip, if 语句使用正则表达式来确保目标 IP 地址由四个点分隔的数字组成

  if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
如果该测试通过,则 if 语句中的代码会在点处将目标 IP 地址分成四个部分,并将这些部分放入数组中
  OIFS=$IFS
  IFS='.'
  ip=($ip)
  IFS=$OIFS
它通过暂时更改 bash 的内部字段分隔符变量来实现这一点,这样 bash 就不是将单词解析为以空格分隔的项目,而是将它们解析为以点分隔的项目。 将目标 IP 地址的值放在括号中并将其分配给自己,从而将其转换为一个数组,其中每个以点分隔的数字都分配给一个数组槽。 现在测试每个单独的部分以确保它们都小于或等于 255,并且保存测试的状态,以便可以将其返回给调用者
  [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
          && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
  stat=$?
请注意,无需测试数字是否大于或等于零,因为正则表达式测试已经消除了任何不只包含点和数字的内容。

Mitch Frazier 是 Emerson Electric Co. 的嵌入式系统程序员。自 2000 年代初以来,Mitch 一直是 Linux Journal 的贡献者和朋友。

加载 Disqus 评论