makefileでsedを使う

makefileでsedを使う

makefileでcygwinパスをWindowsパスに変更したいと思います。このために私は使用しています

CURDIR := `pwd`
WINDIR := $(shell echo $(CURDIR) | sed -e "s/\/cygdrive\/\(.\)/\1:/" | sed -e 's/\//\\/g')

gnumake を使用してこの makefile を実行すると、次のエラーが発生します。

sed.exe: -e expression #1, char 8: Unterminated `s' command

しかし、cygwinシェルから直接次のコマンドを実行すると、目的の出力が得られます。

$: pwd | sed -e "s/\/cygdrive\/\(.\)/\1:/" | sed -e 's/\//\\/g'

上記のコマンドは、シェルで何の苦情もなくうまく実行されます。この問題が発生したのはなぜですか。考えられる解決策は何ですか?

ベストアンサー1

見ている問題を説明するために2番目のsedコマンドを使用すると、問題が発生します。

sed -e 's/\//\\/g'

make\エスケープに使用できる特殊文字%および(単一バックスラッシュ)\\に変換できるエスケープシーケンスとして機能します。\

%バックスラッシュは、2つ以上の連続したバックスラッシュが続く場合を除いてそのまま保存されるため、問題を引き起こすことなく維持され\/ます(これが問題を引き起こす唯一の場所である理由です)。\/

したがって、sed実行される実際のコマンドは次のようになります。

sed -e 's/\//\/g'

たとえば、別の区切り文字を使用すると、コマンドがどのように不完全であるかを確認する方が簡単です#

sed -e 's#/#/g'

まず、#閉じる区切り記号(この場合)がありません。さらに、代替結果は予想されるaの/代わりにaになります。\

追加のバックスラッシュを追加することで問題を解決できます(または2つも可能です)。

sed -e 's/\//\\\/g'

しかし、このコードを読んでいる人にとっては、これは奇妙に思えるかもしれないので、何が起こっているのかを説明するためにコメントを追加することをお勧めします。

もう一つの良いアイデアは倍増することです。すべてmakeバックスラッシュを使用して、レイヤーの1つをエスケープシーケンスとして明示的に使用します。

sed -e 's/\\//\\\\/g'

ああ、まだ悪いです…Except以外の区切り文字を使用すると役に立ちますが、#おそらくそれほど多くはありません。

sed -e 's#/#\\\\#g'

ここで使用する特定のケースsed、つまりCygwinパスをWindowsパスに変換する場合は、実際に使用できます。cygpath --windows、@HaiVuがコメントで指摘したように。

おすすめ記事