1つの正規表現を置き換えてから、最初の正規表現と一致しないすべての行で2番目の正規表現を置き換えます。

1つの正規表現を置き換えてから、最初の正規表現と一致しないすべての行で2番目の正規表現を置き換えます。

例アクション:行にが含まれている場合はfooそれをに置き換えbar、それ以外の場合はbaz行に追加します。

sed -e s/foo/bar/ -e s/$/baz/最初のコマンドが一致しているかどうかにかかわらず、2番目のコマンドが実行されるため、機能しません。sedゲームが終了したら、次の行に移動するようにゲームに指示する方法はありますか?

答え1

t正常な交換後に次のサイクルを開始するには、ラベルなしでコマンドを使用できます。

$ cat ip.txt 
a foo 123
xyz
fore
1foo

$ sed -e 's/foo/bar/' -e t -e 's/$/baz/' ip.txt
a bar 123
xyzbaz
forebaz
1bar

マニュアルから:

tタグ(テスト)

最後の入力行を読み取った後、または条件分岐を実行してから交換が成功した場合にのみラベルに分岐します。ラベルは省略できます。この場合、次のサイクルが開始されます。

答え2

より強力な方法awkスクリプト:

awk '{ if (/foo/) gsub(/foo/, "bar"); else $0 = $0 "baz" }1' file

またはより短く:

awk '{ if (!gsub(/foo/, "bar")) $0 = $0 "baz"; }1' file

答え3

この試み:

sed -e '/foo/!s/$/baz/g' -e s/foo/bar/g

答え4

それを見つけました:

sed -e '/foo/{s//bar/;p;D};s/$/baz/' 

説明する:

  • 以下を使用して、複数のsedコマンドをリンクして;グループ化できます。{}
  • /foo/このパターンを含むすべての行を選択しますfoo
  • s//bar/s/foo/bar/同じ - 空のパターンは、最後の検索を繰り返すことを意味します(この場合)foo
  • p印刷パターンスペース(交互の線)を表します。
  • D現在行を消去して次の行に移動するという意味です。
  • s/$/baz/baz渡す必要がある行を前のルールに追加するタスクの2番目の部分を実行します。

関連情報