在 bash (awk) 中如何转义斜杠

3

我希望能够从Apache日志文件中获取一行及其后面的所有行,以下是我希望简化的内容:

# Convert epoch to format used in log file
gtime=$(date -d @$etime +"%d/%b/%Y:%T")  # "17/Nov/2015:16:36:45"
# Escape the slashes
g_tim=$(echo $gtime | sed 's/\//\\\//g') # "17\/Nov\/2015:16:36:45"
# Grab 
lines=$(awk '/$g_tim/,0' access.log)

如果我不需要使用两个变量,那就更好了,而且我肯定还犯了其他各种错误。

日志文件的示例行:

djerk.nl:80 79.134.133.108 - - [17/Nov/2015:18:51:52 +0100] "GET /wordpress/2015/null HTTP/1.1" 103 16544 "http://www.djerk.nl/wordpress/2015/cisco-lacp-config-for-aruba-ap" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36"
djerk.nl:80 92.27.44.117 - - [17/Nov/2015:18:52:28 +0100] "GET /djerk_nl.pac HTTP/1.1" 403 1147 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36"

1
昨晚可能太晚了,我没注意到编辑按钮... - dmgeurts
2个回答

7
您想打印从匹配17/Nov/2015:16:36:45的行到结尾的所有内容。那么,为什么不使用这个语法呢?
awk '$0 ~ /pattern/ {f=1} f' file

当该模式第一次出现时,会设置一个标志。从那时起,f条件为True,这样所有行都会被打印直到文件结束。

在你的情况下,

awk -v date="$(date -d @$etime +"%d/%b/%Y:%T")" '$0~date {f=1}f' file

2
不错的建议 +1 是的,我认为这正是 OP 所需要的。 - anubhava
1
非常好,谢谢。可惜我发现了一个工作流问题,但那是另一个问题了。我认为在提取最后5分钟的日志行时,跟踪行号会更容易,而不是每行日期。 - dmgeurts
1
@dmgeurts 有趣的命令。你可能想要添加-5秒或其他内容来补偿crontab可能出现的问题。 - fedorqui
1
@dmgeurts 我的错,我没有解释清楚。我想说的是,如果你担心时间会丢失一些数据,你也可以将“date”变量设置为一些额外秒数的值,比如(我不知道这是否正确)date --date='5 minutes ago + 5 sec' - fedorqui
@dmgeurts,您能在您的问题中添加一些示例输入吗?(或者也可以添加一个新的问题)使用mktime(),您可能能够完成这个日期比较。 - fedorqui
显示剩余5条评论

1
根据您的评论,似乎您并不是真正想要“抓取一行及其后面的所有行”,而是想要打印从给定时间戳开始或之后的所有行。代码如下:
$ cat tst.awk
BEGIN { FS="[][ /:]+"; mths="JanFebMarAprMayJunJulAugSepOctNovDec" }
f { print; next }
{ logTime = sprintf("%04d%02d%02d%02d%02d%02d",$8,(match(mths,$7)+2)/3,$6,$9,$10,$11) }
logTime >= tgtTime { f=1 }

$ awk -v tgtTime="$(date -d @"$etime" +"%Y%m%d%H%M%S")" -f tst.awk file

请注意,我更改了date时间规范参数以生成新的时间戳格式进行比较。

1
你说得完全正确。我错误地假设一天中没有一个秒钟没有Apache日志条目。我错得离谱,事后看来,这是一个非常糟糕的假设。让我想知道什么更快。在每行中搜索字符串直到找到匹配项?(while!= result; etime +1)<<粗略的表示法,但我希望你能理解我的意思。还是从日志文件中提取每行的时间代码以计算时期并进行比较?我喜欢你的代码,我有很多东西要学习。谢谢你的分享。 - dmgeurts
刚刚发现日志文件中还包含IPv6地址。这些地址被分割后会造成混乱...我需要清理解析的数据,但是该怎么做呢... wantedLines=$( awk -v tgtTime="$etime" 'BEGIN { FS="[][ /:]+"; mths="JanFebMarAprMayJunJulAugSepOctNovDec" } f { print; next } { logTime = sprintf("%04d%02d%02d%02d%02d%02d",$8,(match(mths,$7)+2)/3,$6,$9,$10,$11) } logTime >= tgtTime { f=1 }' $log_file ) - dmgeurts
你评论了错误的答案,你应该与你选择为正确答案的作者讨论你的问题/需求。 - Ed Morton
我已更改所选答案,因为您的答案比较时间戳,而我之前选择的答案寻找精确匹配,这是我在选择它作为最佳答案后发现的。也许下次我需要等待更长时间才能选择最佳答案? - dmgeurts
1
@dmgeurts 嗯,你可能需要从一开始就让自己的想法清晰明了,因为我们不能每次添加新要求时都更改答案:) - fedorqui
@fedorqui 真的,真的,我道歉。 - dmgeurts

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接