以下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
我假设第二个分支中的.*
我会消耗(读取:跳过?)第一次出现[0: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
fgrep
中的固定字符串*filter
的第一个file
,如果找到,请在包含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 :(得分:0)
自sed
以来略有不同的做法,对于换行线来说很糟糕......
基本上,我将所有内容放在一行中,用@
替换换行符,使用贪婪匹配替换换行符,最后再将换行符放回...
$ cat input | tr '\n' '@' | sed s'/\(\*filter.*\[0:0\]\)/@@\1@TESTLINEADDEDBYSED/' | tr '@' '\n'
someline
someline
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
TESTLINEADDEDBYSED
someline
如果文件中的行数很大,这是一种糟糕的方法!