Lek*_*eyn 37 bash makefile escaping
我正在config.mk
使用一个将由Makefile使用的bash脚本动态生成.该文件构造为:
cat > config.mk <<CFG
SOMEVAR := $value_from_bash1
ANOTHER := $value_from_bash2
CFG
Run Code Online (Sandbox Code Playgroud)
如何确保生成的文件确实包含内容$value_from_bash*
,而不是扩展/解释的内容?我可能需要逃避$
到$$
并\
到\\
,但是否有其他字符需要进行转义?也许有一个我没有听说过的特殊字面作业?
太空似乎也很麻烦:
$ ls -1
a b
a
$ cat Makefile
f := a b
default_target:
echo "$(firstword $(wildcard ${f}))"
$ make
a
Run Code Online (Sandbox Code Playgroud)
如果我使用f := a\ b
它的工作原理(使用引号f := 'a b'
也不起作用,makefile只会将其视为常规字符)
Lek*_*eyn 52
好的,事实证明,Makefile几乎不需要自行转义,但shell解释器执行的命令需要转义.
在Makefile中具有特殊含义且需要转义的字符是:
#
评论)成为\#
$
变量的开头)变成了$$
新行不能插入变量中,但为了避免破坏Makefile的其余部分,请在前面添加反斜杠,以便忽略换行符.
太糟糕了,反斜杠本身无法转义(\\
仍将是,\\
而不是\
你想象的那样).这使得无法在字符串的末尾放置文字斜杠,因为它将使用换行符或后续注释的散列值.一个空格可以放在行的末尾,但也可以放在变量本身中.
配方本身被解释为一个shell命令,没有任何花哨的转义,所以你要自己逃避数据,只是想象你正在编写一个shellcript并从其他文件中插入变量.这里的策略是把变量单引号和逃避只能'
用'\''
(关闭串,插入文字'
,并开始一个新的字符串).示例:mornin' all
变为'morning'\'' all'
等同于"morning' all"
.
第一个字+通配符问题是由于其中包含空格的文件名被视为单独的文件名firstword
.此外,wildcard
使用\
so 扩展转义x\ y
是匹配作为一个单词,x y
而不是两个单词.
似乎在互联网上找不到这个问题的完整答案,所以我终于坐下来,为Windows案例弄清楚了。
具体来说,“视窗案”指的是在Windows中是有效的文件名,这意味着它们不包含字符\
,/
,*
,?
,"
,^
,<
,>
,|
,或换行符。对于Make而言,它也意味着\
并且/
都被视为有效的目录分隔符。
一个例子将比我能解释的更好。基本上,如果您尝试匹配此文件路径:
Child\a$b {'}(a.o#$@,&+=~`),[].c
Run Code Online (Sandbox Code Playgroud)
然后,您必须编写以下规则:
all: Child\\a$$b\\\ \\\ {'}(a.o\#$$@,&+=~`),[].o
%.o: %.c
$(CC) '$(subst ','"'"',$(subst \,,$(subst \\,/,$+)))'
Run Code Online (Sandbox Code Playgroud)
盯着它看了很长时间,它开始有点儿遥不可及了。
这在我的MSYS2环境中有效,因此我认为它是正确的。