Bash 变量插值混乱

Bash 变量插值混乱

我正在尝试了解 Bash 变量插值。

我想用来readlink显示符号链接指向的路径。

如果我使用字符串它就可以工作。

$ echo "$(readlink -- ~/.gitconfig)"
/Users/jord/.dotfiles/gitconfig

由于某种原因,当我尝试使用变量而不是字符串时它不起作用。

$ file="~/.gitconfig"
$ echo "$(readlink -- $file)"

除空白行外,不打印任何内容。

如果我做同样的事情,但用dirname(作为示例),变量插值就会按我预期的方式工作。

$ file="~/.gitconfig"
$ echo "$(dirname -- "$file")"
~

我究竟做错了什么?

答案1

~~引号中的Bash 参考手册的相关部分以。。开始

如果单词以不带引号的波浪符号 ( ~) 开头,则...

要查看差异,请比较:

file="~/.gitconfig"
echo "$file"
file=~/".gitconfig"
echo "$file"

在您的第一个示例中,$(…)first 起作用,并且在其上下文中~未加引号。因此,它会按预期进行扩展。

$file当它“不起作用”时,您的包含文字~POSIX 标准称

字扩展的顺序如下:

波浪符号扩展 […]、参数扩展 […]、命令替换 […] 和算术扩展 […] 应从头到尾执行。[…]

由于波浪号扩展是在参数扩展之前执行的,因此扩展到的变量~/something不会进一步扩展到正确的路径。

请记住,在某些情况下~,或对于~/您的 shell 来说是特殊的,但对于(几乎?)任何其他工具来说,它都不是有效路径。当它起作用时,这是因为 shell 首先发挥了它的“魔力”,而其他工具看到了已经扩展的路径(例如/Users/jord)。

请注意你最后一个例子中的波浪符号扩展没有工作,您仍然会得到文字~,而且对于 shell 来说,如果不使用额外的技巧(例如eval),就无法对其进行处理。dirname不会出现任何问题,因为它适用于字符串。它不关心给定的路径是否有效、是否存在等。它基本上只是搜索最后一个非斜杠组件并将其与尾随斜杠一起丢弃(如果有)。

也可以看看这个答案

相关内容