帮酷LOGO
  • 显示原文与译文双语对照的内容


問題:

我有一個按IP地址排序的日誌文件,我想找到每個唯一IP地址的出現次數。 我如何在bash中實現這個? 可能列出ip旁邊出現的次數,例如:

5.135.134.16 count: 5
13.57.220.172: count 30
18.206.226 count:2

等等。

以下是日誌的示例:

5.135.134.16 - - [23/Mar/2019:08:42:54 -0400]"GET/wp-login.php HTTP/1.1" 200 2988"-""Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
5.135.134.16 - - [23/Mar/2019:08:42:55 -0400]"GET/wp-login.php HTTP/1.1" 200 2988"-""Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
5.135.134.16 - - [23/Mar/2019:08:42:55 -0400]"POST/wp-login.php HTTP/1.1" 200 3836"-""Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
5.135.134.16 - - [23/Mar/2019:08:42:55 -0400]"POST/wp-login.php HTTP/1.1" 200 3988"-""Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
5.135.134.16 - - [23/Mar/2019:08:42:56 -0400]"POST/xmlrpc.php HTTP/1.1" 200 413"-""Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.220.172 - - [23/Mar/2019:11:01:05 -0400]"GET/wp-login.php HTTP/1.1" 200 2988"-""Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.220.172 - - [23/Mar/2019:11:01:06 -0400]"POST/wp-login.php HTTP/1.1" 200 3985"-""Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.220.172 - - [23/Mar/2019:11:01:07 -0400]"GET/wp-login.php HTTP/1.1" 200 2988"-""Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.220.172 - - [23/Mar/2019:11:01:08 -0400]"POST/wp-login.php HTTP/1.1" 200 3833"-""Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.220.172 - - [23/Mar/2019:11:01:09 -0400]"GET/wp-login.php HTTP/1.1" 200 2988"-""Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.220.172 - - [23/Mar/2019:11:01:11 -0400]"POST/wp-login.php HTTP/1.1" 200 3836"-""Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.220.172 - - [23/Mar/2019:11:01:12 -0400]"GET/wp-login.php HTTP/1.1" 200 2988"-""Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.220.172 - - [23/Mar/2019:11:01:15 -0400]"POST/wp-login.php HTTP/1.1" 200 3837"-""Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.220.172 - - [23/Mar/2019:11:01:17 -0400]"POST/xmlrpc.php HTTP/1.1" 200 413"-""Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
13.57.233.99 - - [23/Mar/2019:04:17:45 -0400]"GET/HTTP/1.1" 200 25160"-""Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36"
18.206.226.75 - - [23/Mar/2019:21:58:07 -0400]"GET/wp-login.php HTTP/1.1" 200 2988"https://www.google.com/url?3a622303df89920683e4421b2cf28977""Mozilla/5.0 (Windows NT 6.2; rv:33.0) Gecko/20100101 Firefox/33.0"
18.206.226.75 - - [23/Mar/2019:21:58:07 -0400]"POST/wp-login.php HTTP/1.1" 200 3988"https://www.google.com/url?3a622303df89920683e4421b2cf28977""Mozilla/5.0 (Windows NT 6.2; rv:33.0) Gecko/20100101 Firefox/33.0"
18.213.10.181 - - [23/Mar/2019:14:45:42 -0400]"GET/wp-login.php HTTP/1.1" 200 2988"-""Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
18.213.10.181 - - [23/Mar/2019:14:45:42 -0400]"GET/wp-login.php HTTP/1.1" 200 2988"-""Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
18.213.10.181 - - [23/Mar/2019:14:45:42 -0400]"GET/wp-login.php HTTP/1.1" 200 2988"-""Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"

回答 1:

對於地址列表,可以使用 grepuniq,並再次對它的進行循環,以便計算:

for i in $(<log grep -o '^[^ ]*' | uniq); do
 printf '%s count %dn'"$i" $(<log grep -c"$i")
done

grep -o '^[^ ]*' 從開頭(^)輸出每個字元直到每行的第一個空格,uniq刪除重複的行,從而為您留下IP地址列表。 由於命令替換,for循環遍歷此列表,列印當前處理的IP,然後是「count 」和計數。 後者由 grep -c 計算,它計算至少有一個匹配的行的數目。

運行示例

$ for i in $(<log grep -o '^[^ ]*'|uniq);do printf '%s count %dn'"$i" $(<log grep -c"$i");done
5.135.134.16 count 5
13.57.220.172 count 9
13.57.233.99 count 1
18.206.226.75 count 2
18.213.10.181 count 3

回答 2:

你可以使用 cutuniq 工具:

cut -d ' ' -f1 test.txt | uniq -c
 5 5.135.134.16
 9 13.57.220.172
 1 13.57.233.99
 2 18.206.226.75
 3 18.213.10.181

說明:

  • cut -d ' ' -f1 :提取第一個欄位( ip地址)
  • uniq -c: 報告重複的行並顯示出現的次數

回答 3:

如果不需要特定的輸出格式,那麼我建議已經發布了基於 cut + uniq的應答。

如果你真的需要給定的輸出格式,那麼在Awk中執行它的單程方式就是

awk '{c[$1]++} END{for(i in c) print i,"count:" c[i]}' log

當輸入已經排序時,這有點不理想,因為它不必要地將所有IP存儲到內存中 - 在預先排序的情況下(更直接等同於uniq -c)這樣做的更好但更複雜的方法是:

awk '
 NR==1 {last=$1} 
 $1!= last {print last,"count:" c[last]; last = $1} 
 {c[$1]++} 
 END {print last,"count:" c[last]}
'

示例

$ awk 'NR==1 {last=$1} $1!= last {print last,"count:" c[last]; last = $1} {c[$1]++} END{print last,"count:" c[last]}' log
5.135.134.16 count: 5
13.57.220.172 count: 9
13.57.233.99 count: 1
18.206.226.75 count: 2
18.213.10.181 count: 3

回答 4:

以下是一個可能的解決方案:

IN_FILE="file.log"
for IP in $(awk '{print $1}'"$IN_FILE" | sort -u)
do
 echo -en"${IP}tcount:"
 grep -c"$IP""$IN_FILE"
done
  • file.log 替換為實際文件名。
  • 命令替換表達式 $(awk '{print $1}'"$IN_FILE" | sort -u) 將提供第一列的唯一值的列表。
  • 然後 grep -c 將在文件中計算每個值。
$ IN_FILE="file.log"; for IP in $(awk '{print $1}'"$IN_FILE" | sort -u); do echo -en"${IP}tcount:"; grep -c"$IP""$IN_FILE"; done
13.57.220.172 count: 9
13.57.233.99 count: 1
18.206.226.75 count: 2
18.213.10.181 count: 3
5.135.134.16 count: 5

回答 5:

一些 Perl:

$ perl -lae '$k{$F[0]}++; }{ print"$_ count: $k{$_}" for keys(%k)' log 
13.57.233.99 count: 1
18.206.226.75 count: 2
13.57.220.172 count: 9
5.135.134.16 count: 5
18.213.10.181 count: 3

這與steeldriver方法的 awk相同,但是在Perl中。-a 使perl自動將每個輸入行分割成 array @F,後者的第一個元素( IP ) 是 $F[0] 。 因此,$k{$F[0]}++ 將創建散列 %k,它的密鑰為 IP,它的值是每個IP被查看的次數。 }{ 是"在處理所有輸入之後,在最末尾執行其餘操作"的時髦 perlspeak 。 最後,腳本將迭代哈希的鍵並列印當前密鑰( $_ ) 及它的值( $k{$_} ) 。

因這裡,人們不認為perl強制你編寫看起來像隱含的圖案的腳本,這是一樣的:

perl -e '
 while (my $line=<STDIN>){
 @fields = split(//, $line);
 $ip = $fields[0];
 $counts{$ip}++;
 }
 foreach $ip (keys(%counts)){
 print"$ip count: $counts{$ip}n"
 }' <log

回答 6:

可以能這不是操作需要;但如果我們知道IP地址長度將限製為 15個字元,可以使用 uniq 命令

$ uniq -w 15 -c log
5 5.135.134.16 - - [23/Mar/2019:08:42:54 -0400].. .
9 13.57.220.172 - - [23/Mar/2019:11:01:05 -0400].. .
1 13.57.233.99 - - [23/Mar/2019:04:17:45 -0400].. .
2 18.206.226.75 - - [23/Mar/2019:21:58:07 -0400].. .
3 18.213.10.181 - - [23/Mar/2019:14:45:42 -0400].. .

選項:

-w N 在行中不多於 N 字元

-c 將按出現的次數對行進行前綴

另外,對於精確格式化的輸出,我更喜歡 awk ( 也應用於IPV6地址),ymmv 。

$ awk 'NF { print $1 }' log | sort -h | uniq -c | awk '{printf"%s count: %dn", $2,$1 }'
5.135.134.16 count: 5
13.57.220.172 count: 9
13.57.233.99 count: 1
18.206.226.75 count: 2
18.213.10.181 count: 3

注意,如果 uniq 不是相鄰的,則不會檢測到輸入文件中的重複行,因這裡可以能需要對文件進行 sort


回答 7:

FWIW,python 3:

from collections import Counter
with open('sample.log') as file:
 counts = Counter(line.split()[0] for line in file)
for ip_address, count in counts.items():
 print('%-15s count: %d' % (ip_address, count))

輸出:

13.57.233.99 count: 1
18.213.10.181 count: 3
5.135.134.16 count: 5
18.206.226.75 count: 2
13.57.220.172 count: 9

回答 8:
cut -f1 -d- my.log | sort | uniq -c

說明:在破折號上分割my.log分割的第一個欄位 - 並對其進行排序。 uniq 需要排序的輸入 -c 告訴它計數發生。





Copyright © 2011 HelpLib All rights reserved.    知识分享协议 京ICP备05059198号-3  |  如果智培  |  酷兔英语