【问题标题】:Check for IP validity检查 IP 有效性
【发布时间】:2012-12-08 12:18:11
【问题描述】:

如何在 shell 脚本中检查 IP 地址的有效性,即在 0.0.0.0255.255.255.255 的范围内?

【问题讨论】:

标签: linux shell


【解决方案1】:

如果您使用的是 bash,则可以对模式进行简单的正则表达式匹配,而无需验证四边形:

#!/usr/bin/env bash

ip=1.2.3.4

if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
  echo "success"
else
  echo "fail"
fi

如果您被 POSIX shell 卡住,那么您可以使用 expr 来做基本相同的事情,使用 BRE 而不是 ERE:

#!/bin/sh

ip=1.2.3.4

if expr "$ip" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null; then
  echo "success"
else
  echo "fail"
fi

请注意,expr 假定您的正则表达式锚定在字符串的左侧,因此初始的 ^ 是不必要的。

如果验证每个四边形小于 256 很重要,您显然需要更多代码:

#!/bin/sh

ip=${1:-1.2.3.4}

if expr "$ip" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null; then
  for i in 1 2 3 4; do
    if [ $(echo "$ip" | cut -d. -f$i) -gt 255 ]; then
      echo "fail ($ip)"
      exit 1
    fi
  done
  echo "success ($ip)"
  exit 0
else
  echo "fail ($ip)"
  exit 1
fi

或者甚至可能使用更少的管道:

#!/bin/sh

ip=${1:-1.2.3.4}

if expr "$ip" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null; then
  IFS=.
  set $ip
  for quad in 1 2 3 4; do
    if eval [ \$$quad -gt 255 ]; then
      echo "fail ($ip)"
      exit 1
    fi
  done
  echo "success ($ip)"
  exit 0
else
  echo "fail ($ip)"
  exit 1
fi

或者,如果你的 shell 是 bash,如果你不喜欢算术,你可以使用繁琐的正则表达式进行四边形验证:

#!/usr/bin/env bash

ip=${1:-1.2.3.4}

re='^(0*(1?[0-9]{1,2}|2([0-4][0-9]|5[0-5]))\.){3}'
 re+='0*(1?[0-9]{1,2}|2([‌​0-4][0-9]|5[0-5]))$'

if [[ $ip =~ $re ]]; then
  echo "success"
else
  echo "fail"
fi

这也可以用 BRE 来表示,但是这比我的手指打字要多。

最后,如果你喜欢把这个功能...放在一个函数中:

#!/usr/bin/env bash

ip=${1:-1.2.3.4}

ipvalid() {
  # Set up local variables
  local ip=${1:-1.2.3.4}
  local IFS=.; local -a a=($ip)
  # Start with a regex format test
  [[ $ip =~ ^[0-9]+(\.[0-9]+){3}$ ]] || return 1
  # Test values of quads
  local quad
  for quad in {0..3}; do
    [[ "${a[$quad]}" -gt 255 ]] && return 1
  done
  return 0
}

if ipvalid "$ip"; then
  echo "success ($ip)"
  exit 0
else
  echo "fail ($ip)"
  exit 1
fi

有很多方法可以做到这一点。我只向您展示了一些。

【讨论】:

  • 不错的解决方案。这个对我有用!但是,我观察到,使用您的 ipvalid 函数会修改输入变量(例如,在调用函数后,111.222.333.444 变为 111 222 333 444)。我认为它发生在local -a a=($ip)。我在 macOS 和 Debian 上的 bash 中观察到了它。
  • @focorner,很高兴你喜欢它。 :) 输入变量不会被修改,但 IFS=. 会导致它以不同的方式表示。我怀疑这里最好的解决方案是在本地分配字段分隔符,所以local IFS=.;,这样更改就不会影响函数之外的行为。我在上面的脚本中做了这个改变;如果它仍然对您显示相同的行为,请告诉我。
  • ghoti,你是对的:按照你的建议将 IFS=. 设置为函数内部的本地就可以了。谢谢你。 A+
  • 我已将[[ $ip =~ ^[0-9]+(\.[0-9]+){3}$ ]] || return 1 更改为[[ $ip =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}$ ]] || return 1,以避免00200.0.0.1 有效(它实际上有效,但不是十进制)
  • @MaximKostrikin,这是合理的。四边形中的前导零容易被误解。 020002 呢?一路走下去,^[1-9][0-9]{,2}(\.[1-9][0-9]{,2}){3}$不是更好吗?答案的前面当然提到了这个逻辑极端,RE匹配0到255。我认为我的首选选择是在算术比较开始时简单地使用10#,强制使用base 10.如果有前导零,那就这样吧。
【解决方案2】:

这个单一的正则表达式应该只验证 0.0.0.0 和 255.255.255.255 之间的地址:

#!/bin/bash

ip="1.2.3.4"

if [[ "$ip" =~ ^(([1-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))\.){3}([1-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))$ ]]; then
  echo "success"
else
  echo "fail"
fi

【讨论】:

  • 应该是公认的答案,其他人可以看到“500.400.300.200”是有效的IPv4地址。
  • 这对我来说是一个更好的解决方案,而且更简洁,接受的答案返回三个和两个零(例如:000.00.000.00)为有效。
  • 这是更好的解决方案而且非常简单
【解决方案3】:

使用ipcalc(使用RPM initscripts-9.49.49-1中的版本包测试)

$ ipcalc -cs 10.10.10.257 && echo vaild_ip || echo invalid_ip
invalid_ip

【讨论】:

  • 在我的系统 (Debian Linux) 上不起作用,-s 参数需要一个参数,即使发生错误,返回码也显示为 0。
  • 由于-s 参数,它也无法在 Cygwin 上运行。不过,@JonSouth 下面几篇文章的回答“这个单一的正则表达式......”就像一个魅力。
  • 不起作用。 “-s”选项是“拆分成大小为 n1、n2、n3 的网络。”
  • if ipcalc -c $ip |grep -i invalid ;then echo "Provided IP $ip was invalid" ;fi
  • 来自@T'Saavik 的回答不起作用,因为文本invalid 将找不到,因为它是标准错误输出,应更改为标准输出以使用 grep 过滤
【解决方案4】:

脚本Validating an IP Address in a Bash Script by Mitch Frazier 做你想做的事:

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
}

【讨论】:

  • 你领先我一秒。还要确保检查底部的 cmets,有一些修改可以处理某些情况。
  • 那是 bash,不是 POSIX。 OP 已经指定他使用的是 linux,但不一定是 bash 是 shell。
  • 为了方便起见,您应该将代码编辑到您的帖子中,这样如果链接断开,您的答案不会变得无效。
【解决方案5】:

这一切的典型解决方案似乎都使​​用正则表达式,但在我看来,这可能是一种更好的方法,例如:

if echo "$ip" | { IFS=. read a b c d e;
    test "$a" -ge 0 && test "$a" -le 255 &&
    test "$b" -ge 0 && test "$b" -le 255 &&
    test "$c" -ge 0 && test "$c" -le 255 &&
    test "$d" -ge 0 && test "$d" -le 255 &&
    test -z "$e"; }; then echo is valid; fi

【讨论】:

  • 请注意,这对于字符串 1.2.3.4. 失败(注意尾随 .
  • 这不仅仅是尾随点,这也会在1.2.3.4.a 上给出错误结果。显然,在 bash 中,您可以使用模式匹配,甚至可能是 extglob,在运行答案中的代码之前预测试 $ip,但是您可以在 POSIX 中做什么?
  • @ghoti 说得好。我们可以使用应该为空的第 5 个变量来轻松地使其更加健壮。 (我完全没有声称这是可靠的,但这个编辑肯定更好。)
  • 非常好。在这一点上,我唯一关心的是当/bin/test 尝试使用-ge-le 评估非整数时未处理的(也许是不必要的)输出。但如果有人关心,他们总是可以重定向 stderr。
  • 实际上这将在测试 a.a.a.a 中保释
【解决方案6】:

我调整了所有代码,发现这很有帮助。

#!/bin/bash

ip="256.10.10.100"

if [[ "$ip" =~ (([01]{,1}[0-9]{1,2}|2[0-4][0-9]|25[0-5])\.([01]{,1}[0-9]{1,2}|2[0-4][0-9]|25[0-5])\.([01]{,1}[0-9]{1,2}|2[0-4][0-9]|25[0-5])\.([01]{,1}[0-9]{1,2}|2[0-4][0-9]|25[0-5]))$ ]]; then
  echo "success"
else
  echo "fail"
fi

【讨论】:

  • 接受 1.2.3.4.5、1.2.3.4.5.6、255.255.255.255.255 等。您需要限制八位字节数。
【解决方案7】:

如果有人仍然通过使用正则表达式来寻找答案,下面会起作用 -

echo "<sample ip address>"|egrep "(^[0-2][0-5]{1,2}?\.|^[3-9][0-9]?\.)([0-2][0-5]{1,2}?\.|[3-9][0-9]?\.)([0-2][0-5]{1,2}?\.|[3-9][0-9]?\.)([0-2][0-5]{1,2}?$|[3-9][0-9]?$)"

【讨论】:

    【解决方案8】:

    Perl 有一个很棒的模块 Regexp::Common 用于验证各种事情:

    perl -MRegexp::Common=net -e 'exit(shift() !~ /^$RE{net}{IPv4}$/)' $ipaddr
    

    您可能需要先sudo cpan install Regexp::Common

    我会将它包装在一个函数中:

    valid_ip() {
      perl -MRegexp::Common=net -e 'exit(shift() !~ /^$RE{net}{IPv4}$/)' "$1"
    }
    
    if valid_ip 123.234.345.456; then
      echo OK
    else
      echo INVALID
    fi
    

    【讨论】:

    • 不错。不过,我不建议大多数人直接安装 CPAN。如果可以从包存储库安装模块,您通常会保持系统更清洁和更安全。在 Ubuntu 中,您将使用 sudo apt-get install libregexp-common-perl 在 FreeBSD 中,它将是 cd /usr/ports/textproc/p5-Regexp-Common &amp;&amp; make install
    【解决方案9】:

    我更喜欢使用 ipcalc 来执行此操作,只要我的脚本不必是可移植的。

    ipcalc 1.1.1.355                                                                         
    INVALID ADDRESS: 1.1.1.355
    
    Address:   192.168.1.1          11000000.10101000.00000001. 00000001
    Netmask:   255.255.255.0 = 24   11111111.11111111.11111111. 00000000
    Wildcard:  0.0.0.255            00000000.00000000.00000000. 11111111
    =>
    Network:   192.168.1.0/24       11000000.10101000.00000001. 00000000
    HostMin:   192.168.1.1          11000000.10101000.00000001. 00000001
    HostMax:   192.168.1.254        11000000.10101000.00000001. 11111110
    Broadcast: 192.168.1.255        11000000.10101000.00000001. 11111111
    Hosts/Net: 254                   Class C, Private Internet
    

    这里有一个很棒的页面展示了如何在脚本等中使用它: SleeplessBeastie's Notes

    【讨论】:

      【解决方案10】:

      仍然进行彻底验证的替代版本(这意味着它需要格式正确的 IP 地址,并且每个象限都在允许的值范围内,即 0-255)。在 GNU bash 4.4.20 (Linux Mint 19.3) 上运行良好;在其他地方没有任何承诺,但只要你有 bash 4 就可以了。

      初始格式检查正则表达式是从上面的 shannonman / Mitch Frazier 答案中借用的;剩下的就是我自己的了。

          function isValidIpAddr() {
              # return code only version
              local ipaddr="$1";
              [[ ! $ipaddr =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] && return 1;
              for quad in $(echo "${ipaddr//./ }"); do
                  (( $quad >= 0 && $quad <= 255 )) && continue;
                  return 1;
              done
          }
          function validateIpAddr() {
              # return code + output version
              local ipaddr="$1";
              local errmsg="ERROR: $1 is not a valid IP address";
              [[ ! $ipaddr =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] && echo "$errmsg" && return 1;
              for quad in $(echo "${ipaddr//./ }"); do
                  (( $quad >= 0 && $quad <= 255 )) && continue;
                  echo "$errmsg";
                  return 1;
              done
              echo "SUCCESS: $1 is a valid IP address";
          }
      
          $ isValidIpAddr '192.168.0.1'
          $ echo "$?"
          0
      
          $ isValidIpAddr '192.168.0.256'
          $ echo "$?"
          1
      
          $ validateIpAddr '12.1.10.191'
          SUCCESS: 12.1.10.191 is a valid IP address
      
          $ validateIpAddr '1.1.1.127'
          SUCCESS: 1.1.1.127 is a valid IP address
      
          $ validateIpAddr '1.1.1.1337'
          ERROR: 1.1.1.1337 is not a valid IP address
      

      【讨论】:

        【解决方案11】:

        我们可以使用“ip route save”来做检查。

        valid_addrmask() 
        {
            ip -4 route save match $1 > /dev/null 2>&1
        }
        
        $ valid_addrmask 255.255.255.255 && echo "is valid" || echo "is not valid"
        is valid
        $ valid_addrmask 255.255.255.355 && echo "is valid" || echo "is not valid"
        is not valid
        

        【讨论】:

          【解决方案12】:
          #!/bin/bash
          read -p " ip: " req_ipadr
          #
          ip_full=$(echo $req_ipadr | sed -n 's/^\(\(\([1-9][0-9]\?\|[1][0-9]\{0,2\}\|[2][0-4][0-9]\|[2][5][0-4]\)\.\)\{3\}\([1-9][0-9]\?\|[1][0-9]\{0,2\}\|[2][0-4][0-9]\|[2][5][0-4]\)\)$/\1/p')
          #
          [ "$ip_full" != "" ] && echo "$req_ipadr vaild ip" || echo "$req_ipadr invaild ip"
          

          【讨论】:

            【解决方案13】:

            您可以根据需要复制以下代码并更改 if else 控件的主体

            function checkIP(){
            echo "Checking IP Integrity"    
            ip=$1
            byte1=`echo "$ip"|xargs|cut -d "." -f1`
            byte2=`echo "$ip"|xargs|cut -d "." -f2`
            byte3=`echo "$ip"|xargs|cut -d "." -f3`
            byte4=`echo "$ip"|xargs|cut -d "." -f4`
            
            
            if [[  $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$  && $byte1 -ge 0 && $byte1 -le 255 && $byte2 -ge 0 && $byte2 -le 255 && $byte3 -ge 0 && $byte3 -le 255 && $byte4 -ge 0 && $byte4 -le 255 ]]
            then
                echo "IP is correct"
            else
                echo "This Doesn't look like a valid IP Address : $ip" 
            fi
            }
            checkIP $myIP 
            

            使用存储在名为 myIP 的变量中的 IP 地址调用方法。

            $ip =~ ^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3 }$ - 这部分确保 IP 由 4 个由点 (.) 分隔的块组成,但这里的每个块都允许范围为 0 - 999

            由于每个块的所需范围是 0 - 255,因此请确保可以使用下面的行。

            $byte1 -ge 0 && $byte1 -le 255 && $byte2 -ge 0 && $byte2 -le 255 && $byte3 -ge 0 && $byte3 -le 255 && $byte4 -ge 0 && $byte4 -le 255

            【讨论】:

              【解决方案14】:

              最简单的形式:-

              #!/bin/bash
              while true;
              do
              read -p "Enter a ip: " IP
              echo "${IP}" > ip.txt
              OCT1=$(cat ip.txt | awk -F "." '{print $1}')
              OCT2=$(cat ip.txt | awk -F "." '{print $2}')
              OCT3=$(cat ip.txt | awk -F "." '{print $3}')
              OCT4=$(cat ip.txt | awk -F "." '{print $4}')
              REGEX_IP='^[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}$'
              if [[ ${IP} =~ ${REGEX_IP} ]]
              then
                  if [[ ${OCT1} -gt 255 || ${OCT2} -gt 255 || ${OCT3} -gt 255 || ${OCT4} -gt 255 ]]
                      then
                      echo "Please enter a valid ip"
                      continue
                      fi
              
              break
              else
                      echo "Please enter a valid ip"
                      continue
              fi
              done
              

              这将涵盖所有场景。

              【讨论】:

                【解决方案15】:

                这个怎么样?

                # ip route get 10.10.10.100 > /dev/null 2>&1  ; echo $?
                0
                
                # ip route get 10.10.10.300 > /dev/null 2>&1  ; echo $?
                1
                

                由于“ip”命令检查IP本身的有效性。

                【讨论】:

                • 我不推荐这个。这要求 IP 是可访问的(你需要互联网连接)。因此,如果您断开互联网连接,它将返回 1。
                【解决方案16】:

                也许有用

                #this script verify either a ip address is valid or not as well as public or local ip
                #$1 means supplied first argument
                ip=$(echo $1 | gawk '/^[0-9]{1,3}\.[0-9]{1,3}+\.[0-9]{1,3}+\.[0-9]{1,3}$/{print $0}')
                #regular expression to match pattarn from 0.0.0.0 to 999.999.999.999 address
                
                ip1=$(echo $ip | gawk -F. '{print $1}')
                ip2=$(echo $ip | gawk -F. '{print $2}')
                ip3=$(echo $ip | gawk -F. '{print $3}')
                ip4=$(echo $ip | gawk -F. '{print $4}')
                
                echo "Your ip is : $ip1.$ip2.$ip3.$ip4" #extract four number from the address
                
                #To rectify original ip range 0-255 
                if [[ $ip1 -le 255 && $ip1 -ne 0 && $ip2 -ne 0 &&  $ip2 -le 255 && $ip3 -ne 0 && $ip3 -le 255 && $ip4 -ne 0 && $ip4 -le 255 ]]
                then
                    echo "This is a valid ip address"
                else
                    echo "This is not a valid ip address"
                fi
                
                if [[ $ip1 -eq 198 ]]
                then
                    echo "It may be a local ip address"
                else
                    echo "It may be a public ip address"
                fi
                

                【讨论】:

                  【解决方案17】:
                  #!/bin/bash
                  
                  IP="172.200.22.33.88"
                  p=`echo $IP | tr '.' '\n' | wc -l`
                  echo $p
                  IFS=.
                  set $IP
                  echo $IP
                  a=$1
                  b=$2
                  c=$3
                  d=$4
                  
                  
                  if [[ $p == 4 &&  $a -lt 255 && $b -lt 255 && $c -lt 255 && $d -lt 255 ]]
                  
                  then
                  
                  echo " THIS is Valid IP "
                  
                  else
                  
                  echo "THIS IS NOT VALID IP ADDRESS"
                  
                  fi
                  

                  【讨论】:

                  • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-04-17
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2023-04-06
                  • 2020-11-15
                  相关资源
                  最近更新 更多