Answers:
设置$FOO
不足时报价。您还需要引用变量引用:
me$ FOO="BAR * BAR"
me$ echo "$FOO"
BAR * BAR
短答案
就像其他人所说的那样-您应始终引用变量以防止出现奇怪的行为。因此,使用echo“ $ foo”代替echo $ foo。
长答案
我确实认为此示例值得进一步解释,因为正在进行的事情比表面上看起来要多。
我可以看到您困惑的地方,因为在运行第一个示例后,您可能会以为自己外壳显然在做:
因此,从您的第一个示例:
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命令之前将其删除,但是在第二个示例中,“ \ *”为先前参数扩展的结果,因此不会将其删除。结果,echo收到“ \ *”,这就是它的打印内容。
请注意,第一个示例之间的区别-“ *”不包括在将被“引号删除”删除的字符中。
我希望这是有道理的。最后的结论相同-只需使用引号即可。我只是想解释一下为什么转义不起作用,而转义在逻辑上仅在参数和文件名扩展起作用时才有效。
有关BASH扩展的完整说明,请参阅:
http://www.gnu.org/software/bash/manual/bashref.html#Shell-Expansions
我将在此旧线程中添加一些内容。
通常你会用
$ echo "$FOO"
但是,即使使用这种语法,我也遇到了问题。考虑以下脚本。
#!/bin/bash
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1"
在*
需要传递逐字到curl
,但也会出现同样的问题。上面的示例将不起作用(它将扩展为当前目录中的文件名),也不会\*
。您也无法引用,$curl_opts
因为它将被识别为的一个(无效)选项curl
。
curl: option -s --noproxy * -O: is unknown
curl: try 'curl --help' or 'curl --manual' for more information
因此,如果将bash
变量$GLOBIGNORE
应用于全局模式,我建议使用该变量来完全防止文件名扩展,或者使用set -f
内置标志。
#!/bin/bash
GLOBIGNORE="*"
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1" ## no filename expansion
适用于您的原始示例:
me$ FOO="BAR * BAR"
me$ echo $FOO
BAR file1 file2 file3 file4 BAR
me$ set -f
me$ echo $FOO
BAR * BAR
me$ set +f
me$ GLOBIGNORE=*
me$ echo $FOO
BAR * BAR
SELECT * FROM etc.
,这是唯一可行的方法。
echo "$FOO"