sed
;次の置換を実行するにはどうすればよいですか?:
前:
hello hello hello
hello hello hello
後:
hello world hello
hello hello hello
言い換えると; the[〜#〜] n [〜#〜]thパターンの発生?
(またはこの場合;the2ndパターンの発生?)
任意のPOSIXsed
の場合:
$ sed -e'/hello/{' -e:1 -e'$!N;s/hello/world/2;t2' -eb1 -e\} -e:2 -en\;b2 <file
hello world hello
hello hello hello
最初の一致/hello/
の後、ループが発生します。
ループ:1
内で、各N
ext行をパターンスペースに読み取り、2
ndオカレンスに対してのみs
ubstituteコマンドを実行します。置換が成功したかどうかをt
estします。はいの場合、ループ:2
に遭遇します。そうでない場合は、b1
でループを繰り返します。
ループ:2
の内側では、ファイルの終わりまで残りの行を出力するだけです。
このアプローチでは、2つの間のすべてのものがパターン空間に格納されることに注意してくださいhello。最初と2番目が互いに離れている場合、巨大なファイルで問題になります。
2つのsed
sを使用すると、より簡単になります。実際、多くのことがあり、少なくともマルチコアシステムでは、そのようになっていることがよくあります高速。
_: infile =;<<"" \
sed -e's/$/ /;s/hello/&\n\n/g' -e'# marks lines with " $" and splits matches' |
sed -e:n -e's/ $//;t' -eG -e'# sets up a test label, branches for " $"' \
-e's/o\n\{20\}$/o world/' -e'# stacks a byte per match, edits nth match' \
-e'x;N;x;N;s/\n\n*//;tn' -e'# completes the stacking; recycles to top' \
>outfile
hello hello hello hello hello hello hello hello hello
hello hello hello hello hello hello hello hello hello
hello hello hello hello hello hello hello hello hello
hello hello hello hello hello hello hello hello hello
hello hello hello hello hello hello hello hello hello
hello hello hello hello hello hello hello hello hello
hello hello hello hello hello hello hello hello hello
_
_hello hello hello hello hello hello hello hello hello
hello hello hello hello hello hello hello hello hello
hello hello world hello hello hello hello hello hello hello
hello hello hello hello hello hello hello hello hello
hello hello hello hello hello hello hello hello hello
hello hello hello hello hello hello hello hello hello
hello hello hello hello hello hello hello hello hello
_
(BSD sed
では、右側の置換フィールドの_\n
_エスケープのn
の代わりにリテラル改行が必要になります)
通常、ストリームエディタを適応させるよりもストリームを適応させる方が簡単です。上記のシーケンスはまさにそれを行います。入力の各行全体を末尾のスペースでマークしますが、それ以外の場合は、hello
の出現ごとに出力行を分割します。次に、2番目のsed
は、スペースで終わっていない行を探して、スタックカウントをインクリメントする必要があることを認識し、20番目に明示的に一致するだけで済みます。
もちろん、それほど厳密である必要はありません。 _\n\{20\}$
_の前に先頭のo
を削除し、置換から除外することができます。これは、from 20番目の一致から最後の入力までのみを置き換えます。または、_\n\{20,25\}
_を実行して、一致範囲のみを処理することもできます。または、\n\{20,25\}\(\n\{15\}\)*$
は、20,25の範囲を処理し、その後は10,15回ごとに処理します。
これは、最後に述べたものと同じ入力が与えられた場合の出力サンプルです...
_hello hello hello hello hello hello hello hello hello
hello hello hello hello hello hello hello hello hello
hello hello world hello world hello world hello world hello world hello world hello hello
hello hello hello hello hello hello hello hello world hello world
hello world hello world hello world hello world hello hello hello hello hello
hello hello hello hello hello world hello world hello world hello world hello world
hello world hello hello hello hello hello hello hello hello
_