2

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]?我在这里有什么误解?

4

2 回答 2

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是固定字符串*filterfile如果找到,则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
于 2013-02-28T11:08:19.347 回答
0

略有不同的方法,因为sed换行很糟糕......

基本上,我将所有内容放在一行中,用 a 替换换行符,@使用贪婪匹配进行替换,最后将换行符重新放回......

$ 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

如果文件中的行数很大,这是一种不好的方法!

于 2013-02-28T11:02:48.777 回答