例アクション:行にが含まれている場合は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番目の部分を実行します。