如何正确使用[[==]]来匹配glob?

时间:2014-09-14 12:56:27

标签: bash glob

Bash的手册页教导[[ == ]]匹配模式。因此,在Bash中,为什么以下内容不能打印matched

Z=abc; [[ "$Z" == 'a*' ]] && echo 'matched'

但以下确实打印matched

Z=abc; [[ "$Z" == a* ]] && echo 'matched'

这不是完全落后的吗?为什么没有引号的a*不会立即展开以列出当前目录中以字母a开头的任何文件名?此外,为什么引用的'a*'在任何情况下都不起作用?

2 个答案:

答案 0 :(得分:2)

不得引用Glob模式以使其有效。

这也应该只用于引用的glob模式,而静态文本仍然是被查询的:

[[ "$Z" == "a"* ]] && echo 'matched'
matched

[[ "$Z" == "ab"* ]] && echo 'matched'
matched

手册页中的解释片段:

  

当使用==和!=运算符时,右边的字符串   运算符被认为是一种模式并根据其匹配   模式匹配下面描述的规则。如果是shell选项   启用了nocasematch,执行匹配而不考虑   字母字符的情况。如果返回值为0   字符串匹配(==)或不匹配(!=)模式和1   除此以外。可以引用该图案的任何部分以强制它   匹配为字符串。

此外,使用[[而不是[的原因之一是[[是一个内置的shell,因此可以有自己的语法,不需要遵循正常的扩展规则(这就是为什么[[的参数不受分词限制的原因)。

答案 1 :(得分:1)

虽然现有答案是正确的,但我并不相信它能说出完整的故事。

Globs有两种用途。在[[ ]]构造内的globs之间的行为存在差异,该构造测试变量的内容与模式和其他globs,其扩展以列出一系列文件。在任何一种情况下,如果你在字符周围加上引号,它将按字面解释而不是扩展。

还值得一提的是,左侧的变量不需要在[[之后引用,因此您可以像这样编写代码:

Z=abc; [[ $Z == a* ]] && echo 'matched'

也可以使用单个===看起来比其他编码背景的人更熟悉,所以我个人更喜欢在bash中使用它。如上所述in the comments,单=是更广泛兼容的,因为它用于测试所有符合POSIX的shell中的字符串相等性,例如[ "$a" = "abc" ]。出于这个原因,你可能也喜欢在bash中使用它。

与往常一样,Greg's wiki包含有关bash中模式匹配主题的一些很好的信息。