我有一个按 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"
您可以使用
cut
和uniq
工具:解释 :
cut -d ' ' -f1
:提取第一个字段(IP地址)uniq -c
:报告重复行并显示出现次数如果您不特别需要给定的输出格式,那么我会推荐已经发布的基于
cut
+uniq
的答案如果您确实需要给定的输出格式,那么在 Awk 中执行此操作的单程方法是
当输入已经排序时,这有点不理想,因为它不必要地将所有 IP 存储到内存中 - 在预先排序的情况下(更直接等效于
uniq -c
),更好但更复杂的方法是:前任。
您可以使用
grep
anduniq
作为地址列表,遍历它们并grep
再次进行计数:grep -o '^[^ ]*'
输出从开头 (^
) 到每行的第一个空格的每个字符,uniq
删除重复的行,从而为您留下 IP 地址列表。由于命令替换,for
循环遍历此列表,打印当前处理的 IP,后跟“count”和计数。后者由 计算grep -c
,它计算至少有一个匹配的行数。示例运行
这是一种可能的解决方案:
file.log
为实际文件名。$(awk '{print $1}' "$IN_FILE" | sort -u)
将提供第一列的唯一值列表。grep -c
将计算文件中的每个值。一些 Perl:
这与Steeldriver 的 awk 方法相同,但在 Perl 中。导致 perl 自动将
-a
每个输入行拆分为数组@F
,其第一个元素(IP)是$F[0]
。因此,$k{$F[0]}++
将创建 hash%k
,其键是 IP,其值是每个 IP 被看到的次数。“}{
在处理完所有输入后,在最后做剩下的工作”是时髦的 perlspeak。因此,最后,脚本将遍历散列的键并打印当前键 ($_
) 及其值 ($k{$_}
)。而且,只是为了让人们不会认为 perl 强迫你编写看起来像神秘涂鸦的脚本,这是相同的东西,形式不那么简洁:
也许这不是 OP 想要的;但是,如果我们知道 IP 地址长度将限制为 15 个字符,则可以
uniq
单独使用命令来更快地显示来自巨大日志文件的具有唯一 IP 的计数:选项:
-w N
比较不超过N
行中的字符-c
将按出现次数为行添加前缀或者,对于我更喜欢的精确格式输出
awk
(也应该适用于 IPV6 地址),ymmv。请注意,
uniq
如果它们不相邻,则不会检测输入文件中的重复行,因此sort
文件可能需要。FWIW,Python 3:
输出:
说明:将 my.log 的第一个字段用破折号分割
-
并排序。uniq
需要排序输入。-c
告诉它计算出现次数。