如何/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
使用awk
GNUFPAT
并假设双引号内没有内部双引号或括号内没有括号:
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) 的记录。完毕。
sed 's/\[/"&/; s/\]/&"/'
cvsformat -H -d ' '
(这-H
是不读取带有列标题的标题行)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。