我非常难过。我正在搜索多个文件,看起来像这样(通过find
- 所需的开始日期)和管道到grep,所以我可以用这个命令提取一组行:
find logdir/ -type f -regextype sed -regex ".*2016-06-22.*" | while read fname
do
zgrep -a -P -B9 ".*COOKTHE.*slave.*" $fname
done
所以我可以输出这些行:
2017-05-10 12:14:54 DEBUG[dispatcher-1533] something.else.was.here.Pia - http://server:9999/cookout/123123123123/entry c7aab5a3-0dab-4ce1-b188-b5370007c53c request:
HEADERS:
Host: server:9999
Accept: */*
User-Agent: snakey-requests/2.12.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Timeout-Access: <function1>
CONTENT:
{"operation": "COOKTHE", "reason": "sucker verified", "username": "slave"}
我尝试从第一行匹配中提取整个字符串日期模式(2017-05-10 12:14:54
)数字模式123123123123
,并从最后一行中提取整行匹配。 ({"operation": "COOKTHE", "reason": "sucker verified", "username": "slave"}
)
如何用grep,sed或awk提取这些?
答案 0 :(得分:1)
首先,让我们简化您的初始查询。我认为你不需要正则表达式; globbing更简单,更快速,更清晰。同样,您不需要grep的-P
选项,因为您没有使用PCRE。这也减缓了事情的发展。
find logdir/ -type f -name '*2016-06-22*' | while read fname
do
zgrep -a -B9 '"COOKTHE".*"slave"' "$fname"
done | grep -e ^20 -e '{'
重新创建原始逻辑,但运行速度要快一些。它还添加了一个过滤器,仅显示您要求的两条线。但是,我担心-B9
不是一个好的解决方案,因为可能会有可变数量的标题要跟踪。最后的过滤器也有点简陋,只是为了快速。
这是一个更完整的解决方案:
find logdir/ -type f -name '*2016-06-22*' | while read fname
do
zcat "$fname" | awk '
/^20/ && $6 ~ /^http/ {
split($6, url, "/") # split the URL by slashes
stamp = $1 " " $2 " " url[5] # "2017-05-10 12:14:54 123123123123"
}
/{.*"COOKTHE".*"slave"/ { print stamp; print }
'
done
这会在stamp
变量中保存URL的日期,时间和第5个片段,并且只有在JSON行中匹配时才打印它。我修改了你的正则表达式,包括一个{
来表示JSON的开头以及引号以改善你的匹配,但是你可以把它改成你喜欢的任何东西。此正则表达式不需要前导.*
。
AWK连接相邻的项目,因此$1 " " $2 " " url[5]
仅表示第一列的值,空格,第二列,另一个空格,然后是URL的第5项(注意“http:”后面的空项)。
这不会告诉您匹配文本来自哪个文件(与grep -H
比较)。要做到这一点,你想要:
zcat "$fname" | awk -v fname="$fname:" '
# … (see above)
/{.*"COOKTHE".*"slave"/ { print fname stamp; print fname $0 }
'
如果你正在寻找的JSON字符串始终被放置和间隔,你可以改为使用最终条款$2 ~ /"COOKTHE"/ && $NF ~ /"slave"/
来提高awk的速度(实际上,它能够更快地失败)。
答案 1 :(得分:0)
awk 解决方案:
awk 'NR==1{ sub(/http:\/\/[^\/]+\/[^\/]+\//,"",$6);
print $1,$2,substr($6,1,index($6,"/")-1)}END{ print $0 }' input
输出:
2017-05-10 12:14:54 123123123123
{"operation": "COOKTHE", "reason": "sucker verified", "username": "slave"}
答案 2 :(得分:0)
… | while read fname
do
zcat "$fname" | tr '\n' '\f' |
grep -o -P '\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d.*?COOKTHE[^}]*\}' |
tr '\f' '\n'
done
如果您的输入已包含formfeed-characters(\f
),则可以使用不应出现在输入中的任何其他字符。