使用 awk 或 bash 中的类似工具确定唯一行的数量

使用 awk 或 bash 中的类似工具确定唯一行的数量

我正在使用 AWK 读取我拥有的自定义日志文件。格式如下:

[12:08:00 +0000] 192.168.2.3 98374 "CONNECT 192.168.2.4:8091 HTTP/1.0" 200

现在,我已将 AWK(来自 bash)设置为读取整个日志,分析每一行并抓取包含“CONNECT”的每一行,虽然这可行,但是它并不能帮助我发现唯一的客户端。

实现此目的的方法是以某种方式进行过滤,以便分析每行的这一部分:“CONNECT 192.168.2.4:8091 HTTP/1.0”

如果有办法抓取日志文件中的所有行,然后比较它们,并仅将相似的行计为一行。例如:

 [12:08:00 +0000] 192.168.2.3 98374 "CONNECT 192.168.2.6:8091 HTTP/2.0" 200
 [12:08:00 +0000] 192.168.2.3 98374 "CONNECT 192.168.2.9:8091 HTTP/2.0" 200
 [12:08:00 +0000] 192.168.2.3 98374 "CONNECT 192.168.2.2:8091 HTTP/2.0" 200
 [12:08:00 +0000] 192.168.2.3 98374 "CONNECT 192.168.2.9:8091 HTTP/2.0" 200

在这种情况下,我需要的答案是 3,而不是 4。因为有 2 行是相同的,所以只有 3 行是不同的。我需要一种使用 AWK 自动化的方式来实现这一点。

如果有人能伸出援手那就太好了。

答案1

您可以让 awk 计算唯一实例,如下所示:

awk -F\" '/CONNECT/ && !seen[$2] { seen[$2]++ } END { print length(seen) }' logfile

输出:

3

CONNECT这将从哈希数组中包含的行中收集第一个双引号字符串seen。当到达输入末尾时,seen将打印元素的数量。

答案2

sed -re 's/.*"([^"]*)".*/\1/' <logfile> |sort |uniq

Awk 变体:awk -F'"' {print $2} <logfile> |sort |uniq

添加-cuniq以获取每个匹配行的计数,或|wc -l获取匹配行的数量。

答案3

通过 sort | uniq 运行日志文件应该会过滤掉重复的行,但我想问一下为什么会有这些行。它们真的是重复的吗?

如果它们是合法的日志条目,而您想要的只是一个不重复的行的客户端的唯一列表(第二个字段),那么对@Thor 的脚本进行简单修改就可以得到您想要的东西:

awk '
/CONNECT/ {
  if (seen[$0] == 0) {
    clients[$3]++
  }
  seen[$0]++ 
} 
END {
  for (i in clients) {
    print i
  }
}'

对于您给出的样本,其结果是:

192.168.2.3

这不像 Thor 的脚本那么紧凑,但是我通常发现,一旦我写了这样的东西,我就想对这些行本身做更多的事情,所以我把看到的数组(跟踪唯一行的数量)留在了那里。

相关内容