为什么波形符 (~) 不在双引号内展开?

为什么波形符 (~) 不在双引号内展开?

根据这个答案根据我自己的理解,波浪号扩展到主目录:

$ echo ~
/home/braiam

现在,每当我希望 shell 扩展工作时,即使用诸如 、 之类的变量名称$FOO,并且不要因意外字符、空格等而中断。应该使用双引号"

$ FOO="some string with spaces"
$ BAR="echo $FOO"
$ echo $BAR
echo some string with spaces

为什么这个扩展不能与波浪号一起使用?

$ echo ~/some/path
/home/braiam/some/path
$ echo "~/some/path"
~/some/path

答案1

原因是,因为在双引号内,波形符~没有特殊含义,它被视为文字。

POSIX 定义双引号作为:

用双引号 ( "" ) 括起来的字符应保留双引号内所有字符的字面值,美元符号、反引号和反斜杠字符除外,

...

应用程序应确保双引号前面有一个反斜杠,该反斜杠包含在双引号内。参数“@”在双引号内有特殊含义

除了$`\之外@,其他字符均被视为双引号内的文字。

答案2

波形符扩展POSIX 定义为:

“波形符前缀”由未引用的单词开头的 <tilde> 字符,后跟单词中第一个未加引号的 <slash> 之前的所有字符,或者如果没有 <slash>,则为单词中的所有字符。在赋值中,可以使用多个波形符前缀:[...] 跟在赋值的 <equals-sign> 后面,跟在任何不带引号的 <colon> 后面,或者两者都跟随着。 [...] 如果波形符前缀中的任何字符均未加引号,则 <波形符> 后面的波形符前缀中的字符将被视为来自用户数据库的可能登录名。 [...] 如果登录名为空(即波浪号前缀仅包含波浪号),则波浪号前缀将替换为变量 HOME 的值。如果未设置 HOME,则结果未指定。 [...]

所以最短的答案是“因为它是这样定义的”:引用前缀中的任何字符(包括~, )会抑制扩展。

它还将扩展定义为始终生成单个单词,因此不需要引用:

由波形符扩展产生的路径名应被视为带引号,以防止它被字段分割和路径名扩展更改。

如果某些路径需要引用,但其余路径是波形符前缀,则可以直接将波形符扩展和普通引用结合起来:

$ cat ~/"file name with spaces"

关于更广泛的“原因”:由于分词没有任何可想象的用途~,因此这应该是默认行为,而不是要求将其引用。因为不需要引用它,所以~在引号内赋予特殊含义将是不必要的复杂化。当然,历史原因意味着即使这是可取的,现在也无法改变。

答案3

~起源于 C-shell,早在它被添加到 Korn shell 并后来添加到 POSIX shell 规范之前。

在 C-shell 中,是一个通配符(例如,~通过与扩展相同的例程进行扩展),因此通配符的其余部分不在双引号内执行。*.txt

答案4

虽然这并不能回答为什么要这样设计,但$HOME如果您需要替换,则可以使用它,因为本质上就是这样~做的。

$ echo "$HOME/some/path"
/home/braiam/some/path

相关内容