我有一个简单的 awk 程序 ip.awk 来查找日志文件中 IP 地址出现次数最多的位置。 IP 地址位于第一列:
$cat ip.awk
{ ip[$1]++ }
END {
for (i in ip)
if ( max < ip[i] ) {
max = ip[i]
maxnumber = i }
print maxnumber, " has accessed ", max, " times.", " $1 is: ", $1 }
我使用它来解析文件 access.log,其中的一些示例条目如下所示:
173.13.151.14 - - [11/Sep/2014:23:57:53 +0100] "GET /wp/wp-includes/js/jquery/jquery-migrate.min.js?ver=1.2.1 HTTP/1.1" 200 7404 "http://theurbanpenguin.com/wp/?p=2407" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36"
173.13.151.14 - - [11/Sep/2014:23:57:53 +0100] "GET /wp/wp-content/themes/twentytwelve/js/navigation.js?ver=20140711 HTTP/1.1" 200 1720 "http://theurbanpenguin.com/wp/?p=2407" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36"
173.13.151.14 - - [11/Sep/2014:23:57:53 +0100] "GET /wp/wp-content/uploads/2013/11/tailshadow.png HTTP/1.1" 200 11433 "http://theurbanpenguin.com/wp/?p=2407" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36"
173.13.151.14 - - [11/Sep/2014:23:57:53 +0100] "GET /wp/wp-content/uploads/2014/05/cropped-wp3.png HTTP/1.1" 200 65326 "http://theurbanpenguin.com/wp/?p=2407" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36"
173.13.151.14 - - [11/Sep/2014:23:57:53 +0100] "GET /wp/?p=2407 HTTP/1.1" 200 21717 "https://www.google.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36"
我相信 awk 脚本正确地给出了:
$awk -f ip.awk access.log
68.107.81.110 has accessed 311 times. $1 is: 70.168.57.66
我的困惑在于 $1 的值,根据我的理解,当 awk 在日志文件 access.log 中移动时,应该将其逐行更改为该行第一列中的值。
这是从我在程序末尾添加的检查中检查出来的(“$1 is:”, $1"),因为这返回了最后一行的 IP 地址(日志文件有 30000 多行,所以我制作了一个程序检查此脚本是否确实有效:
$cat testfile.log
1 apple
2 banana
2 banana
3
3
3
4
4
4
4
5
5 flerb
5 flerb
5 flerb
5 flerb
5 flerb , green - tea
6
7
8 grapes 0 and some more filler to make a long line
9
但是当我这样做时,我得到了正确的答案,但当我打印出来时,并没有得到 1 美元的值“9”。我缺少什么?
$awk -f ip.awk testfile.log
5 has accessed 6 times. $1 is:
为了消除另一个变量,我将第一列 ip 地址单独写入一个新文件,并在其上运行 ip.awk,并得到了与在完整日志文件上运行 ip.awk 时完全相同的结果,如预期的那样。我还觉得我错过了一些基本的东西,因为点分十进制 IP 地址如何与数组一起使用?另外:如果我使用 1.0 2.0... 代表 1 2... 我仍然得到正确的答案,但仍然没有 1 美元的价值。
答案:正如 thecarpy 所建议的,问题是当我在测试文件中输入值时,我在最后一个值后按 Enter 键,添加了一个多余的换行符,在解析该行时将 $1 设置为空字符串。
答案1
在awk
程序中,当您读取所有数据后,该END
块就会运行,因此没有要解析的输入行。 (您可能会发现某些实现awk
保留$1
为最后一行的第一个字段。请参阅AWK END 行为是否将最后一行加载到手册页的 $0 中.)
awk
使用关联数组。这意味着您可以使用任何字符串作为索引。数字数组之所以有效,是因为该数组的下标是恰好是单个字符的a[1]
字符串。它可能同样是或什至。 IP 地址的点线四边形只是一个字符串。a[]
1
a[one]
a[banana]