我的日志文件是:
Wed Nov 12 blah blah blah blah cat1
Wed Nov 12 blah blah blah blah
Wed Nov 12 blah blah blah blah
Wed Nov 12 blah blah blah blah cat2
more blah blah
even more blah blah
Wed Nov 12 blah blah blah blah cat3
Wed Nov 12 blah blah blah blah cat4
我想解析出在第一行找到cat的完整多行条目。在sed
和/或awk
中执行此操作的最佳方式是什么?
即。我希望我的解析产生:
Wed Nov 12 blah blah blah blah cat1
Wed Nov 12 blah blah blah blah cat2
more blah blah
even more blah blah
Wed Nov 12 blah blah blah blah cat3
Wed Nov 12 blah blah blah blah cat4
答案 0 :(得分:1)
假设您的日志文件不包含控制字符'\01'
和'\02'
,并且续行以恰好四个空格开头,则以下内容可能有效:
c1=`echo -en '\01'`
c2=`echo -en '\02'`
cat logfile | tr '\n' $c1 | sed "s/$c1 /$c2/g" | sed "s/$c1/\n/g" | grep cat | sed "s/$c2/\n /g"
说明:这将使用ASCII 1(一个永远不应出现在日志文件中的控制字符)替换每个换行符,并使用ASCII 2(另一个控制字符)替换每个序列“newline-space-space-space-space”。然后它用换行重新替换ASCII 1,所以现在每行的多行被放入一行,旧的换行符替换为ASCII 2.这是针对cat的grepped,然后ASCII 2被重新替换为换行 - 空间 - 空间 - 空间 - 空间组合。
答案 1 :(得分:1)
如果你说每一行以空格开头是继续使用(g)awk(这可能来自我的记忆,那么也许它包含一些小的错别字,并且为了更好的可读性和一些额外的换行符):
awk " BEGIN { multiline = 0;}
! /^ / { if (whatever)
{ print; multiline = 1;}
else
multiline = 0;
}
/^ / {if (multiline == 1)
print;
}
"
yourfile
其中whatever
是您检查输出是否应该发生的情况(例如对于猫)。
答案 2 :(得分:0)
这样的东西?
awk 'function print_part() { if(cat) print part } /^ / { part = part "\n" $0; next } /cat[0-9]$/ { print_part(); part = $0; cat = 1; next; } { print_part(); cat=0} END { print_part() }' inputfile
/^ /
正则表达式标识连续行。
/cat[0-9]$/
正则表达式标识您要保留的起始线。
答案 3 :(得分:0)
另一种方法是将RS
设置为普通\n
之外的其他内容。例如:
$ awk -v Pre=Wed 'BEGIN {RS = "\\n?\\s*" Pre} /cat.\n?/ {print Pre $0}' file.log
Wed Nov 12 blah blah blah blah cat1
Wed Nov 12 blah blah blah blah cat2
more blah blah
even more blah blah
Wed Nov 12 blah blah blah blah cat3
Wed Nov 12 blah blah blah blah cat4