你能解释一下 bash 中 printf 命令的内部工作原理吗?

你能解释一下 bash 中 printf 命令的内部工作原理吗?

我偶然发现了这个问题仅用 envsubst 替换特定变量并在其中之一评论这个 shell 示例是:

envsubst "$(printf '${%s} ' ${!PREFIX*})" < infile

有关完整背景,请参阅原始问题,但本质上它是告诉 envsubst 仅替换那些以字符串“PREFIX”开头的环境变量。

但这是如何运作的呢?有人可以解释所涉及的不同“步骤”吗?是先读取infile吗?哪一部分正在执行 grep/find 之类的事情,以便它可以使用文件中的输入?参数“${!PREFIX*}”是某种正则表达式吗?这里是否有一些子外壳魔法?

为了更好地理解它,我使用以下内容创建了自己的 infile:

1: ${VAR1}
2: ${VAR2}
3: ${VAR3}
4: ${PREFIX_1}
5: ${PREFIX_2}
6: ${PREFIX_3} ?
7: ${PREFIX_4} + ${PREFIX_5}
8: ${VAR4}
9: bla bla bla

然后我用 echo 替换了 envsubst,结果是这一行:

echo "$(printf '${%s} ' ${!PREFIX*})" < infile

这个结果:

${PREFIX_1}

所以它有效,但仅适用于第一场比赛。我究竟做错了什么?我期望输出包含所有“PREFIX_”变量 1 到 5。也许当我用 echo 替换 envsubst 时我搞砸了?如果是这样,我如何查看发送到 envsubst 的内容是什么?

答案1

${!prefix_*}是一项 Bash 功能,可扩展为以 . 开头的所有 shell 变量的名称prefix_。命令中的替换printf然后将它们打印在大括号内(它根据需要多次重复格式字符串)。

$ prefix_foo=1 prefix_bar=2
$ printf '${%s}\n' ${!prefix_*}
${prefix_bar}
${prefix_foo}

由于命令替换,它们被丢弃在envsubst的命令行上。扩展和命令替换的结果都涉及分词,但这与默认值${!prefix_*}无关,因为变量名称不能包含空格或通配符。IFS

echo "$(printf '${%s} ' ${!PREFIX*})" < infile

在这里, 的内容infile并不重要,因为echo不会从标准输入读取任何内容。这只会打印以 开头的变量名称PREFIX

相关内容