在 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 shell 上执行以下命令时,我得到了所需的输出:

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

上面的命令运行得很好,没有任何来自 shell 的抱怨。为什么我会面临这个问题以及可能的补救措施是什么?

答案1

为了解释您所看到的问题,它发生在第二个sed命令中:

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

make用作\可用于转义的特殊字符%\\转义序列也是如此,可转换为\(单个反斜杠。)

除了连续两个反斜杠或后跟 时%,反斜杠会逐字保留,因此\/保留为\/并且不会引起任何问题(这就是为什么只有这个地方引起了麻烦。)

所以sed实际执行的命令是:

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

如果您使用不同的分隔符,则更容易看出该命令是如何不完整的,例如#

sed -e 's#/#/g'

首先,#缺少结束分隔符(在本例中为 )。此外,替换得到的是 a/而不是\预期的 a。

您可以通过添加额外的反斜杠来修复它(或者两个也可以):

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

但这对于阅读该代码的人来说可能看起来很奇怪,因此我建议添加注释来解释发生了什么。

另一个好主意是加倍每一个反斜杠,以明确make使用其中一层作为转义序列:

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

呃,还是很糟糕......使用除以外的分隔符#可能会有所帮助,但可能没有那么多:

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

对于您在这里使用的具体情况sed,即将 Cygwin 路径转换为 ​​Windows 路径,您实际上可以使用cygpath --windows,正如@HaiVu 在评论中指出的那样。

相关内容