ファイルに置換コマンドが記述されている場合、sed はファイルの偶数行のみを置換します。

ファイルに置換コマンドが記述されている場合、sed はファイルの偶数行のみを置換します。

すべての置換コマンドをファイル (replace.sed など) に保存し、sed の -f フラグ (sed -f replace.sed InputFile) とともに使用しています。しかし、特定の入力ファイルの偶数行 (つまり、行番号 2、4、6 のみなど) にのみこれらの置換ルールを適用する必要があるという状況に遭遇しました。replace.sed ファイルは別のスクリプトでも使用されているため、このファイルに条件ステートメントを入れることはできません。

答え1

プロセス置換を使用して、sedファイル内のコマンドをその場で調整します。

$ cat replace.sed
s#foo#bar#

$ printf "foo\nfoo\nfoo\nfoo\n" | sed -f replace.sed
bar
bar
bar
bar

$ printf "foo\nfoo\nfoo\nfoo\n" | sed -f <(sed 's#^#2~2#g' replace.sed)
foo
bar
foo
bar

答え2

sed -f <(sed -e 's/.*/2~2{&;}/' replace.sed) InputFile

答え3

他の回答があなたに伝えようsedとしているのは、の住所形式を使用することです。first~step

住所

    … 次のアドレス タイプがサポートされています: …

    初めステップ
      すべて一致ステップ'行目は行頭から初めたとえば、「sed -n 1~2p」は入力ストリーム内のすべての奇数行を出力し、アドレス「2~5」は 2 行目から始まって 5 行ごとに一致します。  初めゼロになることもあります。この場合、 sedは次のように動作します。 ステップ(これは拡張機能です。)

明らかな解決策は、 のすべてのコマンドの前にreplace.sed2~2 または0~2、 のバージョンで機能する場合はsed)を付けて、コマンドが 2 行目から 1 行おきに実行されるようにすることです(つまり、要求どおり、入力ストリームのすべての偶数行)。しかし、 は変更できないとのことですreplace.sed。では、次のステップは(他の回答で特定されているが説明されていないように)、シェルの で一時的な一時ファイルを作成することです。プロセス置換機能、は の出力であるファイルのように動作します。ご質問のとおり、 が単純な置換コマンドのシーケンスである場合、 <(command_list)command_listreplace.sed

sed -f <(sed 's/^/2~2/g' replace.sed)

動作するはずです。

しかし、これには欠点もあります。

  • 1 行に複数のコマンドがある場合、上記は各行の最初のコマンドにのみ影響します。
  • 数値アドレスを持つコマンド (例: ) がある場合42s/Zaphod/Beeblebrox/、それらは などに変換され、2~242…明らかな結果が生じます。
  • また、数値以外のアドレス (例: /windows/s/command/cmd/) を持つコマンドがある場合、上記は完全に失敗します。

これらのケースのいずれかに該当する場合は、

sed -f <(sed -e 's/.*/2~2{&;}/' replace.sed)

sed各行のすべてのコマンドをコマンド グループに入れるバリエーション。

replace.sedしかし、複数行のコマンドがある場合はこれも失敗します。

上記のアイデアを基にして、私は

sed -f <(echo '0~2{'; cat replace.sed; echo '}')

これにより、全体 replace.sedreplace.sedファイルをコマンド グループに追加します。表面的なテストでは、これは他のソリューションで提起した懸念に対処しているようです。非常に長いや非常に複雑なコマンドで問題が発生しても驚きません。

関連情報