正規表現の一致後に行を検索して置換するには、「sed」を使用します。

正規表現の一致後に行を検索して置換するには、「sed」を使用します。

では簡単になりそうですが、そうできるかどうか疑問にawk思います。sedこれは私の入力です。

line 1
line 2
line 3
line 1
line 2
line 3
line 1
line 2
line 3

line 12番目の正規表現を見つけ、それ以降に見つかったすべてを変更するために内部正規表現を作成したいと思いますline 3。出力は次のとおりです。

line 1
line 2
line 3
line 1
line 2
replaced
line 1
line 2
replaced

私は実際にこの入力でのみ動作する「賢い」ソリューションを探しているわけではありません。一般的な検索と置換方法があるかどうかを知りたいです。後ろにと一致しますsed

解決策はどこかにあると思いました。addr出荷書類ビーチ、ところでできることだと説明されていないようで/starting point/,s/...、しようとするとエラーが出ます。

答え1

そのためには、目標線を見た回数を数える必要があります。残念ながら、何でも計算するのはsedPITAです。awkまたはでこれを行うことをお勧めしますperl。たとえば、

$ perl -p -e '$found++ if m/line 1/;
              next if $found < 2;
              s/line 3/replaced/' input.txt 
line 1
line 2
line 3
line 1
line 2
replaced
line 1
line 2
replaced

またはawk:

$ awk '/line 1/ { found++ };
       found < 2 { print ; next };
       { sub(/line 3/,"replaced") ; print }' input.txt 
line 1
line 2
line 3
line 1
line 2
replaced
line 1
line 2
replaced

これらの方法は効果的ですが、最高のソリューション、特にawkバージョン(Perlを直接翻訳したもの)とは遠いです。

ところで、どちらのバージョンも正規表現を使って検索し、計算、検索する正規表現、変える、代替文字列、さらに必要な数までスクリプトにハードコードする代わりに、コマンドラインオプションとして使用できます。

答え2

GNUを使用するsed(0アドレス1の場合):

$ sed '0,/^line 1$/b; /^line 1$/,$ s/^line 3$/replaced/' < file
line 1
line 2
line 3
line 1
line 2
replaced
line 1
line 2
replaced

私たちのb牧場出る最初の0,/^line 1/範囲の場合、これは2番目の範囲に/^line 1$/,$2番目の発生項目に達したときにのみ開始行が表示されることを意味しますline 1

n番目の発生は、以下を使用してawk簡単に見つけることができます。line 1

awk '$0 == "line 1" && ++n == 2, eof {if ($0 == "line 3") $0 = "replaced"}; 1'

(ここではeof初期化されていない他の変数があるので、間違った代表する最初最後範囲には終わりはありません。0リテラルと同じ意味ですが、読みやすくなります!skip1本物現在のレコードを印刷しようとしていますが、使い方が1寛容であるため、すべてのユーザーが認識する必要があり、awkより明確な選択肢は)です{print}


1でGNUを想定しているので、標準ではなく1の後に追加することsedもできます。私たちは別の人が必要です。;more commandsb-e 'more commands'sed

答え3

バッファ(パターン空間)にカウンタを作成し、各行で確認します。

sed '
/^line 1/{x;/11/!s/^/1/;x}
x;/11/{x;b1};x;b
:1;s/^line 3$/replaced/
' file

1カウンターユニットとして使用する

[更新]より良いパフォーマンス:

sed '
/^line 1$/{x;/11/!s/^/1/;x}
/^line 3$/!b
x;/11/!{x;b}
x;s/.*/replaced/
' file

パターンに一致する行でのみカウンタを確認してください -/^line 3$/

答え4

GNU sedを使用すると、保存.スペースにポイントをポイントとして保存して操作を実行できます。

sed -e '
  /^line 1$/,/^line 1$/{//!b
    x;s/^$/./;x;t
    :a;n;s/^line 3$/REPLACED/;ba
  }
' file

もう1つの可能性は、範囲演算子を使用せずにGNU sedで拡張正規表現モードを使用することです。ここで改行文字は\nカウンターとして機能し、予約済みスペースに保存されます。

sed -Ee '
  /^line 1$/H
  x;s/^(\n{1,2}).*/\1/;x
  /^line 3$/G
  /\n.{2}/c REPLACED
  s/\n//g
' file

Perlは同様の方法で同じことを行うことができます。

perl -lpe '
  s/^line 3$/$a?"REPLACED":$&/e
           unless
  m?^line 1$? ... /^line 1$(?{$a++})/;
' file

awk を使用すると、正規表現を変数とうまく組み合わせて 1 ずつ増やすことができます。

awk '
1 < ( k += /^line 1$/ ) &&
sub(/^line 3$/,"REPLACED") ||
1' file

関連情報