Awk
從網路列表中提取 IP
我正在嘗試從包含文本、IPv4 和 IPv6 IP、換行符、IP 範圍等的巨大網路生成列表中提取 IP。
以下是列表中的一個片段:
; Spamhaus DROP List 2016/07/03 - (c) 2016 The Spamhaus Project ; http://www.spamhaus.org/drop/drop.txt ; Last-Modified: Sun, 3 Jul 2016 21:18:32 GMT ; Expires: Sun, 03 Jul 2016 23:26:45 GMT 1.0.1.0/24 223.223.176.0 129.130.100.100 1.160.118.30 91.121.120.228 # 2016-07-05, ns350944.ip-91-121-120.eu, FRA, 1 62.210.111.59 # 2016-07-05, sender9p2.offresduweb.fr, FRA, 1 52.90.253.169 # 2016-07-05, ec2-52-90-253-169.compute-1.amazonaws.com, USA, 13 2a01:4f8:200:2153::2 # 2016-06-27, 2a01:4f8:200:2153::2, DEU, 2 2601:1c1:8801:618c:9864:3f33:7569:38c4 # 2016-06-28, 2601:1c1:8801:618c:9864:3f33:7569:38c4, USA, 2 #last updated 2016.07.04 1733 UTC 1.0.1.0/24 China 1.0.2.0/23 China 1.0.8.0/21 China 1.0.32.0/19 China 1.1.0.0/24 China
如需更大的片段,請參閱pastebin這不是完整的列表順便說一句,因為實際的有超過 44k 行。
我要做的是從列表中只獲取正常 IP (IPv4)。
這是我遇到的上述問題:
grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'
它給了我:
1.0.1.0 223.223.176.0 129.130.100.100 1.160.118.3 198.55.103.144 etc etc
現在,這很好,但我不想要任何以“.0”結尾的東西(例如 1.0.1.0 或 223.223.176.0),因為它們是 IP 範圍而不是實際 IP。因此,我將上述 grep 的輸出通過管道傳輸到 awk 語句,該語句去除了所有以 0 結尾的 IP。
該
grep (IPs) | awk (remove those that end in 0)
解決方案有效,但我想知道是否有更好的方法來做到這一點,並儘量減少使用多個管道 grep(或 sed/awk)。
您可以使用 awk 完成整個任務(當然,假定路徑名):
#!/usr/bin/awk -f /^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[1-9][0-9]*$/ { print; next; } /^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[1-9][0-9]*[^0-9\.:].*$/ { sub("[^0-9.].*$",""); print; }
第一個模式只匹配一個 IPv4(沒有後面的文本),第二個模式允許匹配其他一些文本(並排除帶有冒號的行)。
順便說一句,應該使用**
"^"
和"$"
**跳過不需要的匹配來錨定模式。這顯示為一個腳本,然後可以像任何其他命令(例如帶有 grep 的管道)一樣執行它:
./foo <foo.in
給
129.130.100.100 1.160.118.30 91.121.120.228 62.210.111.59 52.90.253.169
我將匹配拆分為兩個表達式,以簡化處理 IP 地址後的雜散文本。該範圍
[^0-9:\.:]
確保至少有一個流浪字元需要處理。awk 程序不必是腳本,而是自由格式(在製作單個命令字元串時可以丟棄換行符)。但是,結果很難作為單行來閱讀。
與使用
-o
選項grep -E
或-E
選項的建議不同sed
,此awk
解決方案應該適用於任何 POSIX 系統。供參考(POSIX):