我想从 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 在评论中指出的那样。