Shell-Script

grep 文件中的部分 ip 號

  • August 25, 2021

我必須將 IP 地址分類為類,這樣我就可以在我的防火牆中阻止整個類。當我嘗試為 /24 課程做時它工作正常,但在為 /16 課程做時效果不佳。我在 txt 文件中有一個 IP 列表,我想從中進行排序

for IPBL in `cat /tmp/IPs`; do 
 CT=`grep -c ${IPBL%.[0-9]*} /tmp/IPs`
   if [ "$CT" -gt "10" ]; then 
     echo "$IPBL  ${IPBL%.[0-9]*}.0/24  $CT" >>/tmp/spam.lst
   fi
done
cat /tmp/spam.lst |sort -n

所以這很好用,並列印出所有匹配超過 10 個的 ip 是 C 類。

for IPBL in `cat /tmp/IPs`; do 
 CT=`grep -c ${IPBL%.[0-9]*.[0-9]*} /tmp/IPs`
   if [ "$CT" -gt "10" ]; then 
     echo "$IPBL  ${IPBL%.[0-9]*.[0-9]*}.0.0/16  $CT" >>/tmp/spam.lst
   fi
done
cat /tmp/spam.lst |sort -n

所以在這個例子中,大多數匹配都可以,但有些會grep更多,例如。

  • ip8.6.X.X將匹配18.6.X.X168.6.X.X

我試圖放置^${IPBL%.[0-9]*.[0-9]*}grep匹配行的開頭,但沒有幫助,也沒有

grep -E -c "${IPBL%.[0-9]{1,3}.[0-9]{1,3}}" /tmp/IPs

在 ip 號碼中匹配特定數量的數字,而不是放在^字元串前面。

提取完全匹配的最有效方法是什麼?

文件 /tmp/IPs 很大,但是執行 B 遮罩 grep 匹配以下所有 IP 號。正確的是只有 1 個匹配項(第 2 行)。

#IPBL=8.6.144.6
#grep ${IPBL%.[0-9]*.[0-9]*} /tmp/IPs
5.188.62.76
8.6.144.6
39.48.63.128
49.178.61.44
68.61.98.98
73.121.228.65
78.128.60.44
81.68.68.194
86.185.248.61
103.129.178.69
108.61.115.213
108.61.199.100
138.68.224.206
138.68.235.36
142.4.218.69
148.63.196.97
148.64.121.254
148.66.129.250
148.66.130.114
149.202.8.66
173.228.198.65
174.251.128.60
176.78.65.246
176.9.208.67
178.128.68.121
178.62.67.41
178.63.146.46
212.48.66.224

如果我理解正確,您想解析 IP 列表並確定它們屬於哪個 B 類或 C 類網路。如果任何這樣的網路出現超過 10 次,您想在符號中列印 IP 以及它所屬的網路

A.B.C.D   A.B.0.0/16  n

或者

A.B.C.D   A.B.C.0/24  n

分別進入輸出文件spam.lst,其中n是各個子網的實際出現次數。

我為該任務提出了以下awk程序(我們稱之為sort.awk):

#!/bin/awk -f

BEGIN{
   FS=OFS="."
}

NF==4{
   if (FNR==NR) {
       NF=cl
       count[$0]++
       next
   }
   for (n in count) {
       if (index($0,n)==1) {
           if (count[n]<=th) next
           printf "%s %s",$0,n
           for (i=cl;i<4;i++) printf ".0"
           printf "/%d %d\n",8*cl,count[n]
       }
   }
}

你可以這樣稱呼它:

awk -v cl=2 -v th=1 -f sort.awk ips.txt ips.txt> spam.lst

請注意,輸入文件被處理了兩次,因此作為awk!的參數出現了兩次。

該程序的工作原理如下:

  • 您可以將 CIDR 網路類指定為B類網路或C 類網路的awk變數。cl``2``3
  • 您將要阻止整個子網的最小出現次數指定為awk變數th
  • 該程序將輸入和輸出分隔符設置.為將輸入行拆分.為欄位。
  • 該腳本僅考慮包含恰好 4 個欄位的行(IP 的最低完整性檢查)
  • 在第一遍(FNR每個文件行計數器等於NR全域行計數器)中,我們註冊遇到的子網。對於每一行,欄位編號都被削減為值,cl以將其截斷為 B 類或 C 類網路“基地址”。然後,數組中這個(新生成的)基地址的計數器count增加,處理跳到下一行。
  • 在第二遍中,我們遍歷(即在第一遍中註冊的所有子網)的所有索引,以查看目前行上的 IP 是否以該子網地址開頭。count如果相關計數大於門檻值,我們輸出目前 IP 地址,然後輸出基地址,並在右側填充.0和附加 CIDR 表示法的網路遮罩,最後是出現計數。

的輸出cl=2th=1您顯示的範例 IP 列表如下所示

108.61.115.213 108.61.0.0/16 2
108.61.199.100 108.61.0.0/16 2
138.68.224.206 138.68.0.0/16 2
138.68.235.36 138.68.0.0/16 2
148.66.129.250 148.66.0.0/16 2
148.66.130.114 148.66.0.0/16 2

最初的提議旨在整合到現有腳本中,如下所示:

awk -v cl=2 -v nw="8.6.0.0" -F'.' 'BEGIN{split(nw,ref,/\./)} NF==4{for (i=1;i<=cl;i++) {if ($i!=ref[i]) next} printf "%s %s/%d\n",$0,nw,8*cl}' ips.txt

在這裡,我們將解析 IP 列表以檢查它們是否與通過awk變數指定的給定網路基地址屬於同一網路nw

  • 一開始,參考網路基礎 IP 按欄位拆分為一個數組ref
  • 對於遇到的每一行,程序首先檢查它是否包含 4 個欄位(IP 的最小完整性檢查)。如果是這樣,它將比較cl目前行和參考 IP 的第一個欄位。如果其中任何一個不匹配,則跳過該行並繼續處理下一行。如果所有相關欄位都匹配,則列印 IP,然後是 CIDR 表示法的網路。

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