2

この 2 日間、次のsed質問に頭を悩ませていました。

次のファイル(iptables)があります:

someline

someline

*filter

:INPUT ACCEPT [0:0]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [0:0]

someline

sedパターンの検索に使用し*filter、一致した場合は 2 番目のパターンを検索し、2 番目のパターン[0:0]が最後に出現した後に行を追加します。

これにより、(理想的には)次のようになります。

someline

someline

*filter

:INPUT ACCEPT [0:0]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [0:0]

TESTLINEADDEDBYSED

someline

ここのフォーラムは良いスタートを切ってくれましたが、この特定の問題を解決することはできません。

私はこれまでのところ次の解決策を持っていますが、2番目のパターンが最初に出現した後に行を追加します[0:0]:

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

私は.*、2番目のブランチで最初に出現した[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にの固定文字列に対して、*filter見つかっfileた場合は、FOOを含む最後の行の後に行を挿入し[0:0]ます。tacはファイルを逆方向​​に読み取るために使用されるため、最初のオカレンスを見つける方が簡単なので、最後のオカレンスを見つけるためにファイルを2回読み取ったりバッファリングしたりする必要はありません。


ファイルのサイズがそれほど大きくない場合は、次を使用した2パスアプローチを使用し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...

基本的に、改行を に置き換えて、すべてを 1 つの行に配置し、@貪欲な一致を使用して置換を行い、最後に改行を元に戻します...

$ 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 に答える