我偶然发现了这个问题仅用 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
。