不使用 eval 的参数化替换(${foo%bar}、${foo-bar} 等)

Parameterized substitutions (${foo%bar}, ${foo-bar}, etc) without using eval

来自 envsubst 人:

These substitutions are a subset of the substitutions that a shell performs on unquoted and double-quoted strings. Other kinds of substitutions done by a shell, such as ${variable-default} or $(command-list) or `command-list`, are not performed by the envsubst program, due to security reasons.

我想对字符串执行变量替换,支持 ${variable-default}${variable%suffix} 等结构。我不想允许 运行 命令。

显然无法使用 envsubst,另一方面 eval 具有严重的安全隐患。

除了编写自定义插值函数,还有其他可能吗?

bash 4.4 引入了一种新型的参数扩展,它可能会满足您的需求。即,${foo@P} 扩展了 foo 的值,就好像它是一个提示字符串一样,并且提示字符串在显示之前确实经历了一轮扩展。

${parameter@operator}
    Parameter transformation.  The expansion is either a transforma-
    tion  of  the  value of parameter or information about parameter
    itself, depending on the value of operator.  Each operator is  a
    single letter:

    Q      The  expansion is a string that is the value of parameter
           quoted in a format that can be reused as input.
    E      The expansion is a string that is the value of  parameter
           with  backslash  escape  sequences  expanded  as with the
           $'...' quoting mechansim.
    P      The expansion is a string that is the result of expanding
           the value of parameter as if it were a prompt string (see
           PROMPTING below).
    A      The expansion is a string in the form  of  an  assignment
           statement  or  declare  command  that, if evaluated, will
           recreate parameter with its attributes and value.
    a      The expansion is a string consisting of flag values  rep-
           resenting parameter's attributes.

一个简单的例子:

$ foo='${bar:-9}'
$ echo "$foo"
${bar:-9}
$ echo "${foo@P}"
9
$ bar=3
echo "${foo@P}"
3

但是,它仍然允许通过 $(...):

运行 任意命令
$ foo='$(echo hi)'
$ echo "${foo@P}"
hi

另一个警告:它当然也会扩展提示符转义,因此如果您的字符串已经包含一些反斜杠,您的扩展可能比您预期的要多。提示转义和用于 echo -e.

的转义之间存在一些冲突