简短回答
像其他人说的那样-为了防止奇怪的行为,您应该始终引用变量。因此,请使用echo "$foo"而不是echo $foo。
详细回答
我认为这个例子需要进一步解释,因为它比表面上看起来要复杂得多。
我能理解您的困惑,因为在运行第一个示例之后,您可能会想到shell显然正在执行以下操作:
- 参数扩展
- 文件名扩展
所以从您的第一个示例中:
me$ FOO="BAR * BAR"
me$ echo $FOO
参数扩展后等同于:
me$ echo BAR * BAR
文件名扩展后等同于:
me$ echo BAR file1 file2 file3 file4 BAR
如果您在命令行中键入echo BAR * BAR
,您会发现它们是等效的。
所以您可能会想:“如果我转义*,就可以防止文件名扩展。”
因此,从您的第二个示例开始:
me$ FOO="BAR \* BAR"
me$ echo $FOO
参数扩展后应该等同于:
me$ echo BAR \* BAR
文件名扩展后应该等同于:
me$ echo BAR \* BAR
如果您直接在命令行中尝试输入“echo BAR \ * BAR”,它确实会打印“BAR * BAR”,因为转义字符阻止了文件名扩展。
那么为什么使用$foo不起作用呢?
这是因为有第三个扩展-引号删除。从bash手册中可以看到,引号删除是:
在前面的扩展之后,所有未引用的出现的字符‘\’、‘'’和‘"’,如果没有来自上述扩展之一,则被删除。
所以当您直接在命令行中输入命令时,转义字符不是先前扩展的结果,因此BASH在发送给echo命令之前将其删除,但在第2个示例中,“*”是先前参数扩展的结果,因此它不会被删除。因此,echo接收“\ *”,并打印它。
请注意第一个示例和第二个示例之间的区别-“*”不包括在引号删除要删除的字符中。
我希望这很明显。最后结论相同-只需使用引号。我只是想解释为什么转义(逻辑上应该有效,只有参数和文件名扩展在起作用)没有起作用。
有关BASH扩展的完整说明,请参阅:
http://www.gnu.org/software/bash/manual/bashref.html#Shell-Expansions
$FOO
变量扩展,还包括特殊字符*
扩展(请参见https://tldp.org/LDP/abs/html/special-chars.html),或者阅读下面的https://dev59.com/KXVD5IYBdhLWcg3wE3No#104023以充分理解细微差别。 - Chris Beckme$
是什么意思。 - Ömer Anme$
是什么意思。 - undefined