从命令行解析 Apache 日志(带有多个分隔符的日志)

从命令行解析 Apache 日志(带有多个分隔符的日志)

如何/var/log/apache2/other_vhosts_access.log从命令行解析并获取每一列的值?

这肯定是一个非常普遍的问题,并且我尝试过awk,但事情并不像看起来那么简单,因为:

  • 空格用作分隔符
  • 除非我们在引号内"Mozilla/5.0 (Windows NT 10.0; Win64;..."
  • [用于]日期列

在 Debian 上配置的标准 Apache 日志记录示例:

www.example.com:443 1.2.3.4 - - [01/Feb/2021:15:07:35 +0100] "GET /index.html HTTP/1.1" 200 8317 "https://www.example.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"

预期的解析应该能够提取以下任何列:

www.example.com:443
1.2.3.4
-
-
[01/Feb/2021:15:07:35 +0100]
"GET /index.html HTTP/1.1" 
200 
8317 
"https://www.example.com/" 
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36"

答案1

使用awkGNUFPAT并假设双引号内没有内部双引号或括号内没有括号:

awk -v FPAT='"[^"]*"|\\[[^]]*\\]|[^ ]*' '{ for(i=1; i<=NF; i++) print $i }' infile

正则表达式实际上匹配char-X[not char-X]<zero-or-more-of-any-character-until>char-X看到了。

见于人 awk

FPAT
描述记录中字段内容的正则表达式。设置后,gawk 将输入解析为字段,其中字段与正则表达式匹配,而不是使用 FS 的值作为字段分隔符。

答案2

首先在日期位 (1) 周围添加双引号。这将为您提供一个有效的 CSV 文件,其中以空格而不是逗号作为分隔符。然后使用 CSV 解析器将该行读取为 CSV 记录,并使用空格作为字段分隔符 (2)。输出分隔符设置为换行符 (3) 的记录。完毕。

  1. sed 's/\[/"&/; s/\]/&"/'
  2. cvsformat -H -d ' '(这-H是不读取带有列标题的标题行)
  3. csvformat -H -D $'\n'$'...'需要一个能够理解“C 字符串”的 shell,例如bash,否则使用文字换行符)

第二步和第三步可以结合起来,给你

sed 's/\[/"&/; s/\]/&"/' logfile | csvformat -H -d ' ' -D $'\n'

根据 中给定的数据logfile,这会产生

www.example.com:443
1.2.3.4
-
-
[01/Feb/2021:15:07:35 +0100]
GET /index.html HTTP/1.1
200
8317
https://www.example.com/
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36

双引号已从某些条目中删除,因为不再需要它们。

csvformat是其一部分csvkit

相关内容