2017-07-19 53 views
0

我非常难过。我正在寻找(由find -ing所需的开始日期)和管道多行看起来像这样的多个文件到grep这样我就可以提取线组使用此命令:试图匹配与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

对当前输入的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"} 
+0

是的,也错了。我认为OP希望从第一场比赛到最后一场比赛(以及两队之间的比赛)中的所有内容。从Q. – Alfe

+0

中的'-B9'得到的结果是,我实际上在第一行寻找匹配,并抓取整个最后一行。抱歉的误解。 – Sina

+0

我也可以将查找的结果传给这个awk命令?我试图和结果是在两行 – Sina

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 

如果输入已经包含换页字符(\f),你可以使用任何其他字符不应该出现在输入中。

+0

当我运行这个时,我得到了很多'grep:超过PCRE的回溯极限'而没有其他任何产生。 – Sina

+0

然后你的输入对于使用这个技巧来说太大了: -/ – Alfe

+0

如果你在其他地方没有'}',你可以通过插入'|'来解决这个问题。 sed's/\} \ f /} \ n/g''。这会将长的单行输入拆分为大括号后的大块,并可能避免“grep”过程的重载。 – Alfe

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 

这节省了日期,时间,URL在stamp变量并打印第5段,只有当你有在JSON线匹配。我修改了你的正则表达式来包含一个{来表示JSON的开始以及引号来改进你的匹配,但是你可以把它改成任何你喜欢的。这个正则表达式不需要前导或尾随.*

AWK连接相邻的项目,因此$1 " " $2 " " url[5]仅表示第一列,空格,第二列,另一空格的值,然后是URL的第五项(注意“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的速度(实际上,它的能力失效更快)在更长的线上。

+0

发情。非常感谢! – Sina