安全地将 Make 变量传递给 shell 命令



请考虑以下 Makefile:

VAR1=oneword
VAR2=two words
VAR3=three" quoted "words
test:
    printf '>%s< ' "$(VAR1)" "$(VAR2)" "$(VAR3)"
    @echo

如果我运行它,我会得到

$ make test
printf '>%s< ' "oneword" "two words" "three" quoted "words"
>oneword< >two words< >three< >quoted< >words< print

但我想得到与运行以下命令相同的结果:

$ printf '>%s< ' "oneword" "two words" "three" quoted "words"
>oneword< >two words< >three" quoted "words<

假设我无法更改变量,即我必须以某种方式更改对printf的调用。

换句话说:如何将 Make 变量的内容作为一个参数传递给 shell 命令,而不会拆分为多个或任何特定的 shell 效果?

Make 支持 export 指令通过环境传递文本内容:

VAR1=oneword
VAR2=two words
VAR3=three" quoted "words
export VAR1
export VAR2
export VAR3
test:
        printf '>%s< ' "$$VAR1" "$$VAR2" "$$VAR3"
        echo

输出:

$ make test
printf '>%s< ' "$VAR1" "$VAR2" "$VAR3"
>oneword< >two words< >three" quoted "words< echo

我找到了解决方案。它的可读性不是很好,但似乎非常可靠。

这个想法是在外壳级别(')上使用单引号,因为那里没有变量插值或其他奇怪的事情发生。此外,这意味着我们在变量内容中唯一需要担心的字符是单引号,这些字符可以可靠地替换:

VAR1=oneword
VAR2=two words
VAR3=three" quoted 'words
test:
    printf '>%s< ' '$(subst ','\'',$(VAR1))' '$(subst ','\'',$(VAR2))' '$(subst ',''',$(VAR3))'
    @echo

现在我得到了

$ make test
printf '>%s< ' 'oneword' 'two words' 'three" quoted '''words'
>oneword< >two words< >three" quoted 'words< 

请注意 make 如何正确转义',以及 shell 命令如何可靠地接收它。

最新更新