我有一个类似这样的日志文件:
blah blah
blah
blah mypattern blah
blah mypattern blah
blah
blah mypattern blah
blah mypattern blah
blah
我想要一个单行程序从标准输入读取上述内容(即一次通过),用mypattern打印2组行,然后在打印第二组行后直接退出。
如果我只想要一组线,我使用以下单线:
sed '1,/mypattern/d' |sed '/mypattern/!q'
正如你所看到的,这里或那里的一行没什么大不了的。
编辑:这大致是我预期的输出
blah mypattern blah
blah mypattern blah
blah mypattern blah
blah mypattern blah
如果在边界的任何一侧添加或错过一条线,这不是什么大不了的事。重要的是,对于无限输入,如果模式有2个有限部分,则它将终止,其间存在有限的间隙。
答案 0 :(得分:2)
这将计算匹配mypattern
的行组数,并在第二组结束后退出。因此,即使日志文件是无限的,该命令也将终止。
awk '/mypattern/{c+=!f;f=1;print;next} {f=0} c==2{exit}' logfile
说明:
代码有两个变量:f
是一个标志,c
是一个计数器。
/mypattern/{c+=!f;f=1;print;next}
f
是一面旗帜。当我们在匹配mypattern
的一组线之外时,它是零,当我们在里面时,它是一个。
对于匹配mypattern
的任何行,如果这是组中的第一行,即c
,则组计数器f==0
会递增。然后将f
设置为1表示我们现在在一个组中。该行已打印。 next
命令告诉awk
跳过任何剩余的命令并从下一行重新开始。
f=0
如果我们接到这个陈述,那意味着我们在一个群组之外,因此群组标志f
被设置为零。
c==2{exit}
如果我们接到这个陈述,我们就在一个小组之外,如果c==2
,我们已经看到了两个完整的小组。因此,我们exit
awk。
答案 1 :(得分:1)
技术上是一个单行,但可能不像你想要的那样简洁。从好的方面来说,结果是准确的。
awk 'BEGIN { c=0; s=0; } /mypattern/ { if (!s) c++; s=1; print($0); next; } /./ { if (c >= 2) exit; s=0; }'
通过以下测试:
#!/bin/bash -eu
function mkinput {
for i in $(seq $1)
do
hexdump /dev/urandom | head -n $((1 + $RANDOM % 10))
for j in $(seq $((1 + $RANDOM % 10)))
do
echo "blah mypattern blah (i = $i, j = $j)"
done
done
# Produce an infinite stream of input.
hexdump /dev/urandom
}
mkinput 10 | awk 'BEGIN { c=0; s=0; } /mypattern/ { if (!s) c++; s=1; print($0); next; } /./ { if (c >= 2) exit; s=0; }'
可能的输出:
blah mypattern blah (i = 1, j = 1)
blah mypattern blah (i = 1, j = 2)
blah mypattern blah (i = 1, j = 3)
blah mypattern blah (i = 2, j = 1)
blah mypattern blah (i = 2, j = 2)
答案 2 :(得分:0)
这可能适合你(GNU sed):
sed -n '/mypattern/{:a;p;n;//ba;x;s/^/x/;/xx/q;x}' file
对-n
性质使用grep-like
选项。过滤mypattern
并使用保留空间作为何时退出处理的计数器。
或以编程方式:
sed -n '/mypattern/{:a;p;n;//ba;H;x;s/\n/&/2;x;T;q}' file
答案 3 :(得分:0)
Perl,相当长衬,未经测试:
perl -ne 'if (m/mypattern/) { $cnt++ unless $in; $in=1; print; } else { $in=0; exit if $cnt == 2; }'
扩展和适当的Perl"版本以便更好地理解:
my $cnt=0;
my $in=0;
while (<>) {
if m/mypattern/ {
$cnt++ unless $in;
$in = 1;
print;
} else {
$in = 0;
exit if $cnt == 2;
}
}
更新:使用
进行测试aa
aa mypattern aa 1
aa mypattern aa 1
aa mypattern aa 1
aa
aa
aa mypattern aa 2
aa
aa mypattern aa 3
aa mypattern aa 3
aa mypattern aa 3
aa
返回
aa mypattern aa 1
aa mypattern aa 1
aa mypattern aa 1
aa mypattern aa 2