为什么波浪号(〜)不能在双引号内展开?


54

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

$ 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


3
还要注意,当在命令行上提供程序参数而在命令参数上--path ~/myfile扩展但--path=~/myfile不扩展时,这具有不一致的地方。
安赫尔



此主题的一种变化形式是unix.stackexchange.com/questions/279565
JdeBP

Answers:


45

原因是,因为在双引号中,波浪号~没有特殊含义,所以将其视为文字。

POSIX将双引号定义为:

用双引号(“”)括起来的字符应保留双引号内所有字符的文字值,但字符$,反引号和反斜杠除外,

...

应用程序应确保在双引号之前加反斜杠,以将其包含在双引号中。参数“ @”在双引号内具有特殊含义

$`\@,其他字符都被视为双引号内为文字。


9
在这种情况下,我猜您应该使用$HOME
赛斯2014年

11
或者,您不能只引用~例如,ls -l ~/"My Documents"
Andrew Medico 2014年

这是非常不直观的。他们选择这样做的原因是什么?(此答案实际上并没有给出原因,而只是指出了标准,但大概是出于某种原因以这种方式编写了标准。)
iconoclast 2015年

1
@iconoclast如果您真的想要“为什么要用这种方式实现”,请改为阅读Stephane答案。
Braiam

2
所以,@iconoclast,为什么天空是蓝色的?:) :) :)
Jesse Chisholm

32

波浪线扩展由POSIX定义为:

“波浪号前缀”由单词开头的未带引号的 <tilde>字符,其后的所有字符(如果没有<斜线>。... [...]如果没有在波浪号前缀中加引号,则<tilde>之后的波浪号前缀中的字符将从用户数据库中视为可能的登录名。[...]如果登录名为空(即,波浪号前缀仅包含波浪号),则波浪号前缀将替换为变量HOME的值。如果未设置HOME,则结果不确定。[...]

因此,最简单的答案是“因为它是用这种方式定义的”:引用前缀中的任何字符(包括~)都可以抑制扩展。

它还将扩展定义为始终产生单个单词,因此无需使用引号:

由波浪号扩展产生的路径名应被视为已引用,以防止通过字段拆分和路径名扩展对其进行更改。

如果某些路径需要引用,而其余路径是波浪号前缀,则可以将波浪号扩展和普通引用直接组合在一起:

$ cat ~/"file name with spaces"

关于更广泛的“为什么”:由于没有可能进行分词~,因此应该将其作为默认行为,而不是要求使用引号。因为不需要引用它,所以~在引号内赋予特殊含义将是不必要的复杂性。而且,当然,历史原因意味着即使希望这样做,现在也无法更改。


根据本bash指南,波浪号扩展发生空格分隔之前。即使主目录中包含空格,是否可以安全地进行波浪号扩展?通常,当然,您会使用进行此类操作""
Lucretiel

扩展是一个单词;请参阅答案中第二个引用的段落。
Michael Homer

23

~ 起源于C-shell,早在将其添加到Korn Shell并随后添加到POSIX Shell规范中之前。

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


11

尽管这不能回答为什么如此设计,但$HOME如果需要替换,则可以使用它,因为本质上就是~这样。

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

6
这不起作用~otheruser
Johannes Kuhn 2014年

2
没错,但是您可以这样做:THEM =〜otheruser然后使用“ $ THEM / some / path”
融合

1
的变通办法~otheruser表明,~与变量和其他在双引号内引起扩展的东西不同,对待它是一个坏主意。
iconoclast
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.