当找到一个值的最大出现次数时,AWK 简单程序的行为与预期不同

当找到一个值的最大出现次数时,AWK 简单程序的行为与预期不同

我有一个简单的 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[]1a[one]a[banana]

相关内容