2013-02-28 62 views
2

以下sed問題在過去的兩天裏給了我很多頭痛問題。sed兩種模式搜索並追加最後一次發生後的第二種模式

我有以下文件(iptables的)

someline 

someline 

*filter 

:INPUT ACCEPT [0:0] 

:FORWARD ACCEPT [0:0] 

:OUTPUT ACCEPT [0:0] 

someline 

我想用sed搜索模式*filter,如果匹配然後搜索第二圖案[0:0]然後經過添加一行最後一次出現第二種模式。

這則(理想)導致:

someline 

someline 

*filter 

:INPUT ACCEPT [0:0] 

:FORWARD ACCEPT [0:0] 

:OUTPUT ACCEPT [0:0] 

TESTLINEADDEDBYSED 

someline 

論壇在這裏給了我一個很好的開始,但我就是無法破解這一具體問題。

我到目前爲止有以下解決方案,但它與第二圖案[0:0]的第一次出現之後添加行:

sed -n '/\*filter/{:a;N;/^\n/s/^\n//;/\[0:0\]/{!ba;p;s/.*/TESTLINEADDEDBYSED/;};ba}; p' file 

我是假設與.*在第二分支我將消耗下(閱讀:skip?)第一次出現[0:0]? 我在這裏誤解了什麼?

回答

1

如何:

fgrep -q '*filter' file && tac file|awk '!f&&/\[0:0\]/{$0="FOO\n\n"$0;f=1}1'|tac 
someline 

someline 

*filter 

:INPUT ACCEPT [0:0] 

:FORWARD ACCEPT [0:0] 

:OUTPUT ACCEPT [0:0] 

FOO 

someline 

首先fgrepfile固定字符串*filter,如果發現插入行FOO[0:0]最後一個行之後。 tac用於反向讀取文件,所以您不需要讀取文件兩次或緩衝區以查找最後一次出現,因爲它更容易找到第一次出現。


如果文件的大小不是非常大使用二回合方法awk

awk 'FNR==NR{if($0~/*filter/)a=1;if(a&&$0~/\[0:0\]/)b=NR;next}FNR==b{$0=$0"\n\nFOO"}1' file file 

someline 

someline 

*filter 

:INPUT ACCEPT [0:0] 

:FORWARD ACCEPT [0:0] 

:OUTPUT ACCEPT [0:0] 

FOO 

someline 
+1

儘管我的第一個想法只是使用sed,但我必須承認我也喜歡這種簡單而優雅的方法。謝謝! – cybernijntje 2013-02-28 11:19:06

+0

有時候鏈接現有的實用程序可以是一個更簡單的方法,我已經添加了一個兩遍方法,只用'awk'來回答我的對比。 – 2013-02-28 11:37:30

0

略有不同的方法,因爲sed是可怕的用換行...

基本上,我把一切都放在一排,用@更換新行,用貪婪的比賽做我的替換,最後把新行再回來.. 。

$ cat input | tr '\n' '@' | sed s'/\(\*filter.*\[0:0\]\)/@@\[email protected]/' | tr '@' '\n' 
someline 

someline 


*filter 

:INPUT ACCEPT [0:0] 

:FORWARD ACCEPT [0:0] 

:OUTPUT ACCEPT [0:0] 

TESTLINEADDEDBYSED 

someline 

如果文件中的行數很大,這是一種壞的方法!

+0

[UUOC](http://partmaps.org/era/unix/award.html #cat)'tr'\ n''@' 2013-02-28 11:13:17

+0

所以答案就在於製作一個大行(帶分隔符字符),然後編輯該行,然後再將其分成多行?很有意思!謝謝!! – cybernijntje 2013-02-28 11:20:45

+1

@sudo_O - 傷痛!我通常是處理UUoC獎的人:-) – 2013-02-28 11:37:53

相關問題