sedを使用してN番目のテキストが発生する直前にテキストを追加するにはどうすればよいですか?

sedを使用してN番目のテキストが発生する直前にテキストを追加するにはどうすればよいですか?

前の質問を検索しましたが、質問が出た後に追加されました。前に必要です:

 world world
 world world
 world world

したがって、sedは特定のテキストのN番目の発生の先頭に "hello"を追加する必要があります。この場合、4番目の世界に以下を追加します。

world world
world hello world
world world

答え1

sedを使用する必要がある場合は、次のことを試すことができますが、すでに説明したように、sedパスは不安定になります。

sed -e '
  H;1h;g
  s/world/HELLO &/4;tn
  $!d;:n;n;bn
' yourfile

答え2

sed操作に誤ったツールです。使用awkまたはperl交換してください。例えば

$ perl -pe 's/world/++$i == 4 ? "hello world" : $&/ge' input.txt 
world world
world hello world
world world

これは/e、代替演算子の代替部分がs///文字列として解釈されず、Perlコードで実行されるようにするperl regex修飾子を使用することに注意してください。

コードは各一致に対して++$i == 4 ? "hello world" : $&カウンタ変数()を事前にインクリメントし$i、4に等しい場合は一致を「hello world」に置き換え、それ以外の場合は一致を独自の項目($&)に置き換えます。

答え3

「sedを使用してください」と言ったことはわかりますが、現実の世界でこのようなことをする必要がある場合は、すべてのUnixシステムのすべてのシェルでawkを使用してフルワード文字列比較を実行する方法は次のとおりです。パターンに一致するテキストを見つける方法これが重要な理由):

$ awk -v n=4 '{
    for (i=1;i<=NF;i++) {
        if ( ($i == "world") && (++cnt == n) ) {
            $i = "hello " $i
        }
    }
    print
}' file
world world
world hello world
world world

入力内容が次のようになると想像してみてください。

$ cat file
google.com mygoole.comedy
googleycom google.com
google.com google.com

google.comそして、4番目の項目(現在の入力の最後の項目)の前に「hello」を入れようとしています。上記のawkスクリプトを使用すると、次のように変更され$i=="world"ます$i=="google.com"

$ cat file
awk -v n=4 '{
    for (i=1;i<=NF;i++) {
        if ( ($i == "google.com") && (++cnt == n) ) {
            $i = "hello " $i
        }
    }
    print
}' file
google.com mygoole.comedy
googleycom google.com
google.com hello google.com

ここで、sedスクリプトを使用して同じことを試してみてください(特にPOSIX構文のみを使用し、GNU拡張を使用しない場合)。これで、sedスクリプトをin&out代替テキストとして使用すると、より多くの問題が見つかります。hello

答え4

sed 'H;1h;$!d;x;s/world/hello &/4' 

関連情報