既存の #includes の前に追加の include ディレクティブを追加して、多数の C++ ソース ファイルを更新したいと思います。このようなタスクでは、通常、sed を使用した小さな bash スクリプトを使用してファイルを書き換えます。
sed
ファイル内の文字列をすべて置き換えるのではなく、最初に出現した文字列だけを置き換えるにはどうすればよいですか?
もし私が
sed s/#include/#include "newfile.h"\n#include/
すべての #includes を置き換えます。
同じことを達成するための代替案の提案も歓迎します。
ベストアンサー1
sed
「Apple」の最初の出現のみを「Banana」に置き換えるスクリプト
例
Input: Output:
Apple Banana
Apple Apple
Orange Orange
Apple Apple
これは簡単なスクリプトです:編集者注: GNU sed
でのみ動作します。
sed '0,/Apple/{s/Apple/Banana/}' input_filename
最初の 2 つのパラメータ0
と は/Apple/
範囲指定子です。 はその範囲内で実行されるものです。したがって、この場合は「先頭 ( ) から の最初のインスタンスまでのs/Apple/Banana/
範囲内で、を に置き換えます。最初のものだけが置き換えられます。 」0
Apple
Apple
Banana
Apple
背景:従来のsed
範囲指定子はまた「ここから始まる」と「ここから終わる」(両端を含む)の 2 つの正規表現があります。ただし、最も小さい「始まり」は最初の行(1 行目)であり、「ここから終わる」が正規表現である場合、「始まり」の次の行でのみ一致が試行されるため、最も早い終了は 2 行目になります。したがって、範囲は両端を含むため、可能な最小の範囲は「2 行」であり、最小の開始範囲は 1 行目と 2 行目の両方です(つまり、1 行目に出現すると、2 行目の出現も変更されますが、この場合は望ましくありません)。sedは、範囲の終了を にすることができるようにGNU
「疑似」として start を指定できる独自の拡張機能を追加し、正規表現が最初の行に一致する場合は「最初の行のみ」の範囲を許可します。line 0
line 1
または簡略化されたバージョン (空の RE は、//
その前に指定されたものを再利用することを意味するため、これは同等です):
sed '0,/Apple/{s//Banana/}' input_filename
そして中括弧はオプションコマンドの場合はs
、これも同等です:
sed '0,/Apple/s//Banana/' input_filename
これらはすべて GNU でsed
のみ動作します。
homebrew を使用して OS X に GNU sed をインストールすることもできますbrew install gnu-sed
。