2013-05-07 58 views
0

有没有简单的方法来设置sed中的模式范围匹配,让第二个模式查找文件中的最后一次出现?第一[notice]模式后发现如何匹配`sed`中的一行和最后一次出现的范围之间的范围?

sed -r '1,/\[notice\]/d' /var/log/apache2/error.log 

会吐出每一行。但是,如果我能够使它成为最后的[notice]模式,那会更好。

+0

你可以用'tac'阅读反向线条,管道,然后将结果再次输入到“tac”。 – 2013-05-07 16:21:48

+0

是sed必须的? – Kent 2013-05-07 16:29:17

+0

@ChristofferHammarström'tac'对静态文件来说很好,但是如果我做了'tail -f -s 0.1 /var/log/apache2/error.log | sed -r'1,/ \ [notice \]/d''那我就不能用了。 – Jamie 2013-05-08 17:38:35

回答

0

是坏,这可能为你工作(GNU SED):

sed '/\[notice\]/{h;d};x;/./!{x;d};x;H;$!d;x;s/[^\n]*\n//' file 

存储模式和之后在保持空间中的线。在文件的最后打印出这些线条(以前的模式已经被覆盖了)。

的另一种方式,是将整个文件啜到内存中,然后删除不需要的部分(贪婪是你的朋友:):

sed ':a;$!{N;ba};s/.*\[notice\][^\n]*\n//' file 
2

sed的是在一个单一的线为简单取代的优秀工具,对于任何其他的文本操作只是用awk:

$ cat file 
line 1 
[notice] 
line 2 
[notice] 
line 3 

$ awk 'NR==FNR{if (/\[notice\]/) tgt=NR; next} FNR>tgt' file file 
line 3 

上述用途通过2次的文件,第一遍找到线路号最后一次出现的图案和第二次打印您想要的线条。

另一种方法是将整个文件作为单个记录读取,然后在最后一个[notice](和周围空间/换行符)之前将所有内容都删除,例如,与GNU AWK:

$ gawk -v RS='\0' -v ORS= '{sub(/.*\[notice\]\s*/,"")}1' file 
line 3 
+0

感谢您的回复;我应该提到输入文件是流式传输,因此多次传递都具有挑战性。没有? – Jamie 2013-05-08 17:40:54

+0

这并不具有挑战性,这是不可能的。如何识别流中某个模式的最后一次出现? – 2013-05-08 18:14:32

+0

通过缓冲自上次发生以来的数据:可能最终将整个文件读入内存,但可以通过单次传递完成。波通的回答暗示,虽然我没有为我工作。 – Jamie 2013-05-13 16:10:43

0

读取文件一次,可能对大文件

awk '{a[NR]=$0; /notice/ && b=NR} END {for(c=b+1;c<=NR;c++) print a[c]}' 
相关问题