2012-12-08 85 views
15

如何在shell腳本中檢查IP地址的有效性,即在0.0.0.0255.255.255.255的範圍內?檢查IP有效性

+0

你可以試試我的建議張貼在這裏:https://unix.stackexchange.com/a/389565/249079 – Ganapathy

回答

29

如果你正在使用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外殼,那麼你可以使用expr做基本上是一回事,U唱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 
    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 

有很多方法可以做到這一點。我已經向你展示了幾個。

+0

很好的解決方案。這個對我有用!然而,我觀察到,使用'ipvalid'函數來修改輸入變量(例如,在函數被調用後,111.222.333.444變爲111 222 333 444)。我認爲它發生在'local -a a =($ ip)'。我在macOS和Debian上都用bash來觀察它。 – focorner

+1

@focorner,很高興你喜歡它。 :)輸入變量不會被修改,但是'IFS = .'會導致它以不同的方式表達*。我懷疑這裏最好的解決方案是在本地分配字段分隔符,所以'local IFS = .;',以便更改不影響函數之外的行爲。我在上面的腳本中做了這個改變;請讓我知道它是否仍然對你顯示相同的行爲。 – ghoti

+0

ghoti,你是對的:在函數中設置'IFS = .'作爲你的建議。謝謝。 A + – focorner

4

我相信這個腳本做你想做的事:http://www.linuxjournal.com/content/validating-ip-address-bash-script

編輯,包括代碼的建議如下:

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 
} 
+2

您可以通過第二打我給它。還要確保檢查底部的註釋,有幾個修訂來處理某些情況。 – PeterJ

+0

這是bash,而不是POSIX。 OP已經指定他在使用linux,但不一定是bash是shell。 – ghoti

+1

爲方便起見,您應該將代碼編輯到您的文章中,因此如果鏈接發生故障,您的答案不會失效。 – icktoofay

0

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 
+1

很好。雖然,我不會建議大多數人直接安裝CPAN。如果模塊可以通過軟件包存儲庫進行安裝,您通常會保持系統清潔和更安全。在Ubuntu中,你可以'sudo apt-get install libregexp-common-perl'在FreeBSD中,它將是'cd/usr/ports/textproc/p5-Regexp-Common && make install'。 – ghoti

1

典型這個解決方案似乎都使​​用正則表達式,但是對我來說這可能是一個更好的方法來做類似的事情:

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 
+0

請注意,對於字符串「1.2.3.4.」(注意後面的「。」) –

+0

這不會失敗,它也會在1.2.3.4.a文件中產生錯誤的結果。很明顯,在bash中你可以使用模式匹配,甚至可以使用extglob在運行代碼之前預先測試'$ ip',但是你可以在POSIX中做什麼? – ghoti

+1

@ghoti說得很好。我們可以很容易地使用應該是空的第五個變量來更健壯。 (我沒有聲稱這是可靠的,但是這個編輯當然更好。) –

5

使用ipcalc

$ ipcalc -cs 10.10.10.257 && echo vail_ip || echo invalid_ip 
invalid_ip 
+1

不適用於我的系統(Debian Linux),'-s'參數需要一個參數,即使發生錯誤,返回碼也會顯示爲0。 –

+0

由於'-s'參數的原因,無法使它在Cygwin上工作。然而,@JonSouth在下面的幾篇文章中回答了「This single regex ...」。 –

1

這個單一的正則表達式應該驗證只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 
0
#!/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" 
1

我發現下面的紙條HERE我覺得非常方便。

#!/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 
} 
1

我調整了所有的代碼,發現這是有幫助的。

#!/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