【问题标题】:Parsing the access logs解析访问日志
【发布时间】:2020-06-04 05:28:36
【问题描述】:
xx.xx.xx.xx [04/Jun/2020:01:15:45 -0400] 179478 86841 www.abc.com 781 "POST /api/search?type=1234 HTTP/1.0" 200 "-" "IOS" 
xx.xx.xx.xx [04/Jun/2020:01:15:45 -0400] 179478 86841 www.abc.com 781 "POST /api/search?type=333 HTTP/1.0" 200 "-" "IOS" 
xx.xx.xx.xx [04/Jun/2020:01:15:45 -0400] 179478 86841 www.abc.com 781 "POST /api/search?type=1234 HTTP/1.0" 200 "-" "IOS" 
xx.xx.xx.xx [04/Jun/2020:01:15:45 -0400] 179478 86841 www.abc.com 781 "POST /api/search?type=333 HTTP/1.0" 200 "-" "IOS" 
xx.xx.xx.xx [04/Jun/2020:01:15:45 -0400] 179478 86841 www.abc.com 781 "POST /api/search?type=333 HTTP/1.0" 200 "-" "IOS" 

以上是我的访问日志。 使用 ask 命令awk '{ print $9 }' 我可以得到 /api/search?type=1234,但是我现在卡住了。

我正在寻找类型的计数

1234 = 3

333 = 2

可以帮忙

【问题讨论】:

标签: awk


【解决方案1】:

编辑:由于用户在 cmets 中提到 type 关键字可能并不总是出现,因此在此处添加更通用的解决方案。

awk '
match($0,/=[0-9]+/){
  array[substr($0,RSTART+1,RLENGTH-1)]++
}
END{
  for(i in array){
    print i,array[i]
  }
}
'  Input_file


您能否尝试使用所示示例进行以下、编写和测试。

awk '
match($0,/type=[0-9]+/){
  array[substr($0,RSTART+5,RLENGTH-5)]++
}
END{
  for(i in array){
    print i,array[i]
  }
}
'  Input_file

第二个解决方案: 使用 GNU grep + cut + sort + uniq,可能不如 awk 解决方案添加它那么有效在这里作为替代。

grep -oP '.*\?type=\K.*' Input_file | cut -d' ' -f1 | sort | uniq -c

【讨论】:

  • 我正在寻找一般解决方案,但它不适用于此 url /api/version/not/trac?rid=abc:defas-dff
  • @SuhaanaaShah,您能否在您的问题中添加更多示例。也请务必让我们知道要捕捉的模式是什么。
  • @SuhaanaaShah,您能否检查一下我的编辑解决方案,让我知道这是否对您有帮助?
【解决方案2】:

如果顺序不重要,使用index'=' (+1) 快速使用substr,使用数组索引的结果递增数组,例如

$ awk '{a[substr($9, index($9,"=")+1)]++} END{ for (i in a) print i "=" a[i]}' log
333=3
1234=2

数组上方a[] 使用substr($9, index($9,"=")+1) 提取字段9 中'=' 右侧的内容,每次遇到值时递增数组的该元素。

首先计算 index 并确保它不为零,这样您就可以排除字段 9 不包含您的 =[0-9]+ 模式的记录,例如

$  awk '{ndx=index($9,"="); if(ndx) a[substr($9, ndx+1)]++} 
        END{ for (i in a) print i "=" a[i]}
' log
333=3
1234=2

@RavinderSingh13 的回答还在使用 match 的返回值包含记录之前验证了模式(做得很好)

注意:333 出现 3 次,1234 出现 2 次,与您显示的计数相反)


根据评论编辑 re:记录包含非数字跟随 =

如果您需要使用正则表达式来匹配字段内的位置,则需要match(),例如

$ awk '{ndx=match($9,/=[0-9]+/); if(ndx) a[substr($9, ndx+1)]++} 
  END{ for (i in a) print i "=" a[i]}' log
  333=3
  1234=2

index 不允许将正则表达式常量用作find 参数。 (非标准扩展除外)

【讨论】:

  • 我正在寻找一般解决方案,但它不适用于此 url /api/version/not/trac?rid=abc:defas-dff
  • 是的,= 检查仅限于字段 9,但我不排除非数字 - 如果您的日志在该位置包含非数字,则 match() @RavinderSingh13 显示是必须的。 index 不允许将正则表达式常量用作 find 参数。例如,您可以将 index($9,"=") 替换为 match($9,/=[0-9]+/)
猜你喜欢
  • 1970-01-01
  • 2017-08-11
  • 2015-02-21
  • 1970-01-01
  • 2016-02-14
  • 2013-11-22
  • 2012-03-03
  • 2012-07-29
相关资源
最近更新 更多