根据这个答案和我自己的理解,波浪号扩展到主目录:
$ echo ~
/home/braiam
Run Code Online (Sandbox Code Playgroud)
现在,每当我希望 shell 扩展工作时,即使用诸如 的变量名$FOO,并且不要因为意外的字符、诸如空格等而中断。应该使用双引号":
$ FOO="some string with spaces"
$ BAR="echo $FOO"
$ echo $BAR
echo some string with spaces
Run Code Online (Sandbox Code Playgroud)
为什么这种扩展不适用于波浪号?
$ echo ~/some/path
/home/braiam/some/path
$ echo "~/some/path"
~/some/path
Run Code Online (Sandbox Code Playgroud)
cuo*_*glm 58
原因,因为在双引号内,波浪号~没有特殊含义,它被视为文字。
POSIX 将双引号定义为:
用双引号 ( "" ) 括起来的字符应保留双引号内所有字符的字面值,但美元符号、反引号和反斜杠除外,
...
应用程序应确保双引号前有反斜杠以包含在双引号中。参数“@”在双引号内有特殊含义
除了$, `,\和@,其他字符被视为双引号内的文字。
Mic*_*mer 40
POSIX 将波浪号扩展定义为:
“波浪号前缀”由单词开头的未加引号的<波浪号> 字符组成,后跟单词中第一个未加引号的 <斜杠> 之前的所有字符,如果没有 <,则为单词中的所有字符斜线>。在赋值中,可以使用多个波浪号前缀:[...] 跟在赋值的 <equals-sign> 之后,跟在任何未加引号的 <colon> 之后,或者两者都有。[...] 如果没有引用波浪号前缀中的任何字符,则将 <波浪号> 后面的波浪号前缀中的字符视为来自用户数据库的可能登录名。[...] 如果登录名为空(即波浪号前缀仅包含波浪号),则波浪号前缀将替换为变量 HOME 的值。如果未设置 HOME,则结果未指定。[...]
所以最短的答案是“因为它是这样定义的”:引用前缀中的任何字符,包括~,抑制扩展。
它还将扩展定义为始终产生单个单词,因此无需引用:
由波浪号扩展产生的路径名应被视为被引用,以防止它被字段拆分和路径名扩展改变。
如果某些路径需要引用,而其余路径是波浪号前缀,您可以直接将波浪号扩展和普通引用结合起来:
$ cat ~/"file name with spaces"
Run Code Online (Sandbox Code Playgroud)
关于更广泛的“为什么”:由于没有可以想象的 word-splitting 用途~,这应该是默认行为,而不是要求它被引用。因为不需要引用它,所以~在引号内赋予特殊含义将是不必要的复杂化。而且,当然,历史原因意味着即使这是可取的,现在也无法更改。
Sté*_*las 27
~ 起源于 C-shell,早在它被添加到 Korn shell 和后来添加到 POSIX shell 规范之前。
在 C-shell 中,~是一个通配符(*.txt例如,由与扩展相同的例程扩展),所以像其他通配符一样,不在双引号内执行。
mel*_*lds 15
虽然这不能回答为什么它是这样设计的,但$HOME如果你需要替换,你可以使用它,因为这本质上就是~这样做的。
$ echo "$HOME/some/path"
/home/braiam/some/path
Run Code Online (Sandbox Code Playgroud)