$ 内的环境变量扩展(命令替换)

$ 内的环境变量扩展(命令替换)

我在 Debian 上运行 Bash 5.1.4。

我正在编写一个安装后脚本,将配置和其他文件复制到我的主目录中的位置。我在每个文件的开头添加了预期的目的地,并带有前缀;例如:(# DEST: $HOME/.config/mousepad/Thunar当然,在脚本中,文件名将被变量替换,哈希符号将被适当的注释字符替换;这一行出现在前 10 行内,​​不一定出现在第一行,所以我不弄乱shebangs)。

为了获取这些位置,我使用这个命令:head Thunar.acs | egrep "DEST:" | awk '{print $3},它按字面返回$HOME/.config/Thunar;我希望它能够扩大$HOME。我的意思是当我尝试时ls $(head Thunar.acs | egrep "DEST:" | awk '{print $2})出现错误ls: cannot access '$HOME/.config/Thunar/': No such file or directory。我读这个问题并尝试了所选答案中的所有双引号组合,但我仍然收到错误。我该如何解决这个问题?

将变量名称括在大括号中也不起作用。

谢谢!

答案1

命令替换和变量扩展不是递归的。也就是说,当 shell 展开类似$varname或 的内容时$(somecommand),它不会扫描结果以查找要展开的其他$varname实例$(somecommand)。它对结果所做的唯一事情就是尝试将其拆分为“单词”并展开任何看起来像文件名通配符的内容;这些会造成比其他任何事情都更多的麻烦,因此您几乎应该始终对扩展进行双引号,这样它就不会受到影响。

如果您确实想$HOME扩展到实际的主路径,我看到的最简单的方法是将其通过管道传输envsubst(这将扩展任何看起来像环境变量引用的内容,但请注意,它仅适用于环境变量,而不是未导出的 shell 变量),或者已经awk进行替换(这只会执行您告诉它替换的特定变量)。

在展示如何做到这一点之前,我必须反对使用三种工具—— headegrepawk—— 当awk它们完全能够完成整个工作时:

awk '/DEST:/ {print $3}; (NR>=10) {exit}' Thunar.acs

该位完成原来的/DEST:/工作,并取代.egrep(NR>=10) {exit}head -n 10

因此,这里有一个使用版本envsubst

ls "$(awk '/DEST:/ {print $3}; (NR>=10) {exit}' Thunar.acs | envsubst)"

(请注意双引号,以防止分词和通配符扩展做任何奇怪的事情。)

awk这是使用ssub函数进行替换的版本:

ls "$(awk -v home="$HOME" '/DEST:/ {sub("\\$HOME",home,$3); print $3}; (NR>=10) {exit}' Thunar.acs)"

相关内容