説明が補足された、多くの役立つ既存の回答の概要:
ここの例では、単純化された使用例を使用しています。最初の一致する行でのみ「foo」を「bar」に置き換えます。
原因は、使用する(ANSI C-引用符で囲まれた文字列$'...')、サンプル入力ラインを提供するためにbash、kshまたはzshシェルとして想定されます。
GNU sedのみ:
ベンHoffsteinのanwswerの GNUを提供することを示している私達拡張子にするために、POSIX仕様sed、次のことができますその2-アドレスの形式:0,/re/(reここでは、任意の正規表現を表しますが)。
0,/re/正規表現を最初の行でも一致させることができます。言い換えれば、そのようなアドレスが一致すること線を含むまで1行目までの範囲と作成するre-かre1ラインまたは任意の後続ラインで発生します。
- POSIX準拠の形態とは対照的
1,/re/範囲を作成し、それへと線を含めて最大1行目から一致していることを一致reに後続行; 他の言葉で:これは、最初の発生を検出しませんre、上で発生することが発生した場合、一致を第一ラインとも速記の使用防止//、最近使用正規表現の再利用のために(次のポイントを参照してください)。1
同じ正規表現を使用0,/re/するs/.../.../(置換)呼び出しとアドレスを組み合わせる場合、コマンドは事実上、一致する最初の行でのみ置換を実行します。re
sed便利提供し、最も最近適用正規表現再利用するためのショートカット:空、区切り文字のペアを//。
$ sed '0,/foo/ s//bar/' <<<$'1st foo\nUnrelated\n2nd foo\n3rd foo'
1st bar # only 1st match of 'foo' replaced
Unrelated
2nd foo
3rd foo
sedBSD(macOS)などのPOSIX機能のみ(sedGNU でも動作しますsed):
は0,/re/使用できず、フォーム1,/re/がre最初の行(上記を参照)で発生したかどうかを検出しないため、1行目の特別な処理が必要です。
MikhailVSの答えは、ここで具体的な例に入れられたテクニックについて言及しています:
$ sed -e '1 s/foo/bar/; t' -e '1,// s//bar/' <<<$'1st foo\nUnrelated\n2nd foo\n3rd foo'
1st bar # only 1st match of 'foo' replaced
Unrelated
2nd foo
3rd foo
注意:
ここでは、空の正規表現//ショートカットが2回使用されていsます。どちらの場合も、正規表現fooは暗黙的に再利用されるため、複製する必要がないため、コードが短く、保守しやすくなります。
POSIX sedは、ラベルの名前の後や省略など、特定の機能の後に実際の改行を必要とします。tです。スクリプトを複数の-eオプションに戦略的に分割することは、実際の改行を使用する代わり-eになります。通常、改行を挿入する必要がある各スクリプトチャンクを終了します。
1 s/foo/bar/ 置き換える foo見つかった場合、1行目のみをます。その場合t、スクリプトの最後に分岐します(行の残りのコマンドをスキップします)。(t関数は、最新のs呼び出しが実際の置換を実行した場合にのみラベルに分岐します。ここでは、ラベルがない場合、スクリプトの最後に分岐します)。
すなわち、範囲アドレス発生した場合1,//、通常、最初の発生を発見し、ライン2から出発して、意志はありませんと一致し、且つ範囲があろうない現在の行が既にある場合に、アドレスが評価されるので、処理されます2。
逆に、1行目に一致がない場合、 1,// します入力すると、真の最初の試合があります。
正味の効果は、GNU sedの場合と同じ0,/re/です。1行目で発生したかどうかに関係なく、最初の発生のみが置き換えられます。
非範囲アプローチ
ポトンの答えは、範囲の必要性を回避するループ技術を示しています。彼はGNU sed構文を使用しているので、POSIX準拠の同等のものを次に示します。
ループ手法1:最初の一致で置換を実行してから、残りの行をそのまま出力するループに入る:
$ sed -e '/foo/ {s//bar/; ' -e ':a' -e '$!{n;ba' -e '};}' <<<$'1st foo\nUnrelated\n2nd foo\n3rd foo'
1st bar
Unrelated
2nd foo
3rd foo
ループテクニック2、小さめのファイルのみ:入力全体をメモリに読み込み、それに対して単一の置換を実行します。
$ sed -e ':a' -e '$!{N;ba' -e '}; s/foo/bar/' <<<$'1st foo\nUnrelated\n2nd foo\n3rd foo'
1st bar
Unrelated
2nd foo
3rd foo
1 1.61803を用いて何が起こるかの例を提供1,/re/して、後続することなく、s//:
- sed '1,/foo/ s/foo/bar/' <<<$'1foo\n2foo'収率$'1bar\n2bar'。つまり、行番号が最初の行と一致するため、両方の行が更新され、1正規表現(/foo/範囲の終わり)は次の行から開始するためにのみ検索されます。したがって、この場合は両方の行が選択され、両方に対してs/foo/bar/置換が実行されます。
- sed '1,/foo/ s//bar/' <<<$'1foo\n2foo\n3foo' 失敗:sed: first RE may not be empty(BSD / macOS)およびsed: -e expression #1, char 0: no previous regular expression(GNU)を使用します。これは、1行目が処理されているとき(行番号1が範囲の始まりであるため)、まだ正規表現が適用されていないためです。//何も参照していません。
GNUの例外を除いてsedの特別0,/re/な構文、いかなるで始まること範囲ライン数が効果的の使用を排除します//。