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

Safely pass Make variable to shell commands

考虑这个 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

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

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

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 命令如何可靠地接收它。