最初のエントリだけをsedに置き換える方法は?

最初のエントリだけをsedに置き換える方法は?

オリジナルファイル

claudio
antonio
claudio
michele

次のような結果を得るために、「claudio」の最初の項目を「claudia」に変更したいと思います。

claudia
antonio
claudio
michele

私は以下を試しました:

sed -e '1,/claudio/s/claudio/claudia/' nomi

上記のコマンドはグローバル置換を実行します(すべての「claudio」エントリを置き換えます)。なぜ?

答え1

GNUを使用している場合は、以下をsed試してください。

sed -e '0,/claudio/ s/claudio/claudia/' nomi

sedまで終了範囲の正規表現チェックを開始しません。後ろに範囲を開始する行です。

~からman sed(POSIXマンページ、強調鉱山):

2つのアドレスを持つ編集コマンドは、最初のアドレスと一致する最初のパターンスペースから包含範囲を選択する必要があります。Next パターン空間2番目と一致します。

ただし、このアドレスは標準ではなく、他の実装ではサポートされていないGNU拡張0です。sedsed

使用awk

作業範囲はawkあなたの期待に合致します。

$ awk 'NR==1,/claudio/{sub(/claudio/, "claudia")} 1' nomi
claudia
antonio
claudio
michele

説明する:

  • NR==1,/claudio/

    これは、行1から始めて最初の項目で終わる範囲ですclaudio

  • sub(/claudio/, "claudia")

    この代替コマンドは、範囲内にあるときに実行されます。

  • 1

    これはawkの印刷ラインの秘密の略語です。

答え2

GNUの新しいバージョンはsedこの-zオプションをサポートしています。

通常、sedは行末(改行またはキャリッジリターン)まで文字列を読み取り、行を読み取ります。
バージョン 4.2.2 の GNU バージョン sed には、代わりに "NULL" 文字を使用する機能が追加されました。これは、レコード区切り文字としてNULLを使用するファイルがある場合に便利です。一部のGNUユーティリティは、「find . -print0」や「grep -lZ」など、新しい行の代わりにNULLを使用する出力を生成できます。

sed別の行で作業したい場合は、このオプションを使用できます。

echo 'claudio
antonio
claudio
michele' | sed -z 's/claudio/claudia/'

返品

claudia
antonio
claudio
michele

答え3

まとめる

GNU構文:

sed '/claudio/{s//claudia/;:p;n;bp}' file

または(置換したい単語を一度だけ使用する:

sed '/\(claudi\)o/{s//\1a/;:p;n;bp}' file

またはPOSIX構文を使用して:

sed -e '/claudio/{s//claudia/;:p' -e 'n;bp' -e '}' file

すべてのsed、プロセスに適用可能ただ最初のものを見つけると、最初の行にあっclaudioてもできるだけ多くの行が必要になり、1つのclaudio正規表現文字列だけが使用されるため、短くなります。

詳細

変更のみ一行あなたはする必要があります選ぶ1行だけです。

1,/claudio/(質問から)以下を使用して選択します。

  • 最初の行から始める(無条件)
  • 到着Next文字列を含む行claudio
$ cat file
claudio 1
antonio 2
claudio 3
michele 4

$ sed -n '1,/claudio/{p}' file
claudio 1
antonio 2
claudio 3

選ぶどの行を含めるには、claudio次を使用します。

$ sed -n `/claudio/{p}` file
claudio 1
claudio 3

そしてのみ選択最初 claudioファイルで次を使用します。

sed -n '/claudio/{p;q}' file
claudio 1

その後、その行でのみ変更できます。

sed '/claudio/{s/claudio/claudia/;q}' file
claudia 1

これだけ変わるよ最初2 つ以上があっても、その行で正規表現の一致が発生します。最初正規表現に一致する行です。

もちろん、/claudio/正規表現は次のように単純化できます。

$ sed '/claudio/{s//claudia/;q}' file
claudia 1

次に、欠けている唯一のものは、変更されていない他のすべての行を印刷することです。

sed '/claudio/{s//claudia/;:p;n;bp}' file

答え4

awkフラグを使用して、交換が完了したことを確認できます。そうでない場合は続けます。

$ awk '!f && /claudio/ {$0="claudia"; f=1}1' file
claudia
antonio
claudio
michele

関連情報