Linux

linux & solaris - 將網路遮罩 IP 與普通 IP 分開

  • June 19, 2013

我有帶有 IP 地址和網路遮罩 IP 的文件

我的目標是從file_with_IPs.txt中剪切網路遮罩 IP ,並將它們粘貼到另一個文件中作為file_with_only_netmask_ips.txt

備註 - 網路遮罩 IP 可以是網路遮罩 IP 的任意組合,例如可以從 xxx.xxx.xxx.xxx/1 到 xxx.xxx.xxx.xxx/32 開始

例如

 10.140.4.11    10.140.4.110    
 255.255.0.0    255.255.255.0    
 10.219.39.188  10.219.39.200
 10.219.39.189  10.219.39.145
 10.140.4.12    10.140.4.120
 10.219.39.138   10.219.39.140
 10.219.39.139   10.219.39.239
 255.0.0.0        255.255.0.0
 255.255.255.128    255.255.255.192

所以最後我將在file_with_IPs.txt文件中

 10.140.4.11    10.140.4.110    
 10.219.39.188  10.219.39.200
 10.219.39.189  10.219.39.145
 10.140.4.12    10.140.4.120
 10.219.39.138   10.219.39.140
 10.219.39.139   10.219.39.239

file_with_only_netmask_ips.txt我將只有網路遮罩 IP,如下所示:

 255.255.0.0    255.255.255.0
 255.0.0.0        255.255.0.0
 255.255.255.128    255.255.255.192

請建議將網路遮罩 IP 與普通 IP 分開的最佳方法是什麼?

我需要用 ksh shell 編寫程序,我需要在 Linux 和 Solaris 機器上執行這個程序

備註 perl 一種線性 , sed 和 awk 可以在 ksh 腳本中

一種方法awk

awk '{
   for(i=1;i<=NF;i++) {
       if($i~/^255/) {
           netmask[NR]=i>1?netmask[NR]"\t"$i:$i
       }
       else { 
           regular[NR]=i>1?regular[NR]"\t"$i:$i
       }
   }
}
END {
   for(i=1;i<=NR;i++) {
       if (regular[i]) {
           print regular[i] > "file_with_IPs.txt"
       }
       if (netmask[i]) {
           print netmask[i] > "file_with_only_netmask_ips.txt"
       }
   }
}' file

測試:

$ ls
file

$ cat file
10.140.4.11    10.140.4.110    
255.255.0.0    255.255.255.0    
10.219.39.188  10.219.39.200
10.219.39.189  10.219.39.145
10.140.4.12    10.140.4.120
10.219.39.138   10.219.39.140
10.219.39.139   10.219.39.239
255.0.0.0        255.255.0.0
255.255.255.128    255.255.255.192

$ awk '{
>     for(i=1;i<=NF;i++) {
>         if($i~/^255/) {
>             netmask[NR]=i>1?netmask[NR]"\t"$i:$i
>         }
>         else { 
>             regular[NR]=i>1?regular[NR]"\t"$i:$i
>         }
>     }
> }
> END {
>     for(i=1;i<=NR;i++) {
>         if (regular[i]) {
>             print regular[i] > "file_with_IPs.txt"
>         }
>         if (netmask[i]) {
>             print netmask[i] > "file_with_only_netmask_ips.txt"
>         }
>     }
> }' file

$ ls
file  file_with_IPs.txt  file_with_only_netmask_ips.txt

$ cat file_with_IPs.txt 
10.140.4.11     10.140.4.110
10.219.39.188   10.219.39.200
10.219.39.189   10.219.39.145
10.140.4.12     10.140.4.120
10.219.39.138   10.219.39.140
10.219.39.139   10.219.39.239

$ cat file_with_only_netmask_ips.txt 
255.255.0.0     255.255.255.0
255.0.0.0       255.255.0.0
255.255.255.128 255.255.255.192

通過“網路遮罩 IP”,您似乎是指所有設置位在左側組合在一起的東西。其中只有 32 個,從 /0 到 /32。您可以在 grep 語句中列出它們(或者,更好的是,在您傳遞給的文件中grep -f)。

這種方法很乏味,但很容易;

^0\.0\.0\.0$
^128\.0\.0\.0$
^192\.0\.0\.0$
^224\.0\.0\.0$
⋮

由於它實際上是我們正在尋找的二進制模式,您可以將其轉換回數字,然後對其進行一些位旋轉以確認它與模式匹配。不過,這將是一項實際的程式任務,而不是您與 grep 一起完成的任務。

雖然你可以用 bc 做一些接近的事情。以下是測試方法$ip

(
   echo 'obase=2';
   echo "$ip" | sed -e 's/\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)/\1*(256^3)+\2*(256^2)+\3*256+\4/'
) bc | grep -q '^1*0*$' && echo yes || echo no

如果你把它分解,echo 告訴 bc 以二進制輸出。然後該sed行將 IP 地址轉換為表達式,以計算其數值。255.255.255.0變成255*(256^3)+255*(256^2)+255*256+0. 所以bc看到:

obase=2
255*(256^3)+255*(256^2)+255*256+0

它列印出11111111111111111111111100000000,然後檢查它以匹配^1*0*$模式grep

如果您有一個將 IP 轉換為數字的實用程序,那將消除上述大部分複雜性。不過,可能仍然會比grep帶有模式列表的 慢。

引用自:https://unix.stackexchange.com/questions/79887