当前位置:  开发笔记 > 编程语言 > 正文

如何在bash中转义通配符/星号字符?

如何解决《如何在bash中转义通配符/星号字符?》经验,为你挑选了3个好方法。

例如.

me$ FOO="BAR * BAR"
me$ echo $FOO
BAR file1 file2 file3 file4 BAR

并使用"\"转义字符:

me$ FOO="BAR \* BAR"
me$ echo $FOO
BAR \* BAR

我显然做了一些愚蠢的事.

如何获得输出"BAR*BAR"?



1> finnw..:

设置$ FOO时引用是不够的.您还需要引用变量引用:

me$ FOO="BAR * BAR"
me$ echo "$FOO"
BAR * BAR


这很神秘,为什么会这样?到底是怎么回事?

2> 小智..:

简短的回答

像其他人所说的那样 - 你应该总是引用变量来防止奇怪的行为.所以使用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命令之前将其删除,但在第二个例子中,"\*"是先前参数扩展的结果,因此不会被删除.结果,echo收到"\*",这就是它打印的内容.

请注意第一个示例之间的差异 - "*"不包括在将被删除的字符中删除的字符中.

我希望这是有道理的.最后得出的结论 - 只是使用引号.我只是想我会解释为什么转义,如果只有参数和文件名扩展在起作用,它在逻辑上应该工作,不起作用.

有关BASH扩展的完整说明,请参阅:

http://www.gnu.org/software/bash/manual/bashref.html#Shell-Expansions



3> 小智..:

我将为这个旧线程添加一些内容.

通常你会用

$ 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.`,这是唯一有效的方法.
推荐阅读
有风吹过best
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有