web-dev-qa-db-ja.com

makefile内でのsedの使用

メイクファイル内からcygwinパスをWindowsパスに変更したい。そのために、私は使用しています

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

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

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

ただし、cygwin Shellで次のコマンドを直接実行すると、目的の出力が得られます。

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

上記のコマンドは完全に機能し、シェルからの不満はありません。なぜ私はこの問題に直面しているのですか?可能な解決策は何ですか?

2

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

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

make\をエスケープするために使用できる特殊文字として%を使用するため、\\\(単一のバックスラッシュ)に変換されるエスケープシーケンスです。)

連続する2つのバックスラッシュ以外、または%が後に続く場合、バックスラッシュはそのまま保持されるため、\/\/として保持され、問題は発生しません(そのため、この場所のみトラブルを起こしました。)

したがって、実際に実行されるsedコマンドは次のとおりです。

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

#などの別の区切り文字を使用すると、このコマンドがどのように不完全であるかを簡単に確認できます。

sed -e 's#/#/g'

まず、終了デリミタ(この場合は#)がありません。さらに、置換は意図した/ではなく\を取得しています。

あなたは余分なバックスラッシュを追加することでそれを修正することができます(または2つも動作します):

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

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

もう1つの良いアイデアは、バックスラッシュを2つ2つ二重にして、makeがエスケープシーケンスとして1つのレベルを使用していることを明確にすることです。

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

ええと、それでもかなりひどい... #以外の区切り文字を使用すると、少しは役立つかもしれませんが、おそらくそれほど多くはありません。

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

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

3
filbranden