![$ 内的环境变量扩展(命令替换)](https://linux22.com/image/194413/%24%20%E5%86%85%E7%9A%84%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E6%89%A9%E5%B1%95%EF%BC%88%E5%91%BD%E4%BB%A4%E6%9B%BF%E6%8D%A2%EF%BC%89.png)
我在 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
进行替换(这只会执行您告诉它替换的特定变量)。
在展示如何做到这一点之前,我必须反对使用三种工具—— head
、egrep
和awk
—— 当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)"