帮酷LOGO
0 0 评论
文章标签:命令行  行计数  文件  TEX  Comma  COMM  文本  COM  


問題:

我有一個按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 告訴它計數發生。




文章标签:COM  文件  COMM  文本  TEX  Comma  命令行  行计数  

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