$ bash -c 'echo [[:digit:]]' # bash leaves it as-is
[[:digit:]]
$ zsh -c 'echo [[:digit:]]' # zsh by default complains if no match
zsh:1: no matches found: [[:digit:]]
$ touch 1 3 d i g t
$ bash -c 'echo [[:digit:]]' # now there are two matches
1 3 # note that d, i, g and t do NOT match
因为它们是两种不同的东西。这
{1,2,3}
是一个大括号扩展的例子。该{1,2,3}
结构在看到它之前就被 shell扩展了。echo
你可以看到如果你使用会发生什么set -x
:如您所见,该命令
echo {1,2,3}
扩展为:但是,
[[:digit:]]
是一个POSIX 字符类。当你把它交给echo
时,shell 也会首先处理它,但这次它被作为shell glob处理。它的工作方式与您运行echo *
将打印当前目录中的所有文件的方式相同。但是[[:digit:]]
是一个可以匹配任何数字的shell glob。现在,在 bash 中,如果一个 shell glob 不匹配任何内容,它将被扩展为自身:如果 glob 确实匹配某些内容,则会打印:
在这两种情况下,
echo
只打印 shell 告诉它打印的任何内容,但在第二种情况下,由于 glob 匹配某些东西 (/etc
),它被告知打印那个东西。因此,由于您没有任何名称仅由一位数字组成的文件或目录(这
[[:digit:]]
将匹配),因此 glob 将扩展为自身,您将获得:现在,尝试创建一个名为
5
并运行相同命令的文件:如果有多个匹配文件:
这(有点)记录在关闭此行为
man bash
的选项的解释中:nullglob
如果设置此选项:
{1,2,3}
是大括号扩展,它扩展到列出的单词而不考虑它们的含义。[...]
是一个字符组,用于文件名扩展(或通配符或 glob),类似于星号*
和问号?
。它匹配其中列出的任何单个字符,或作为命名组成员的字符,例如[:digit:]
是否列出了这些字符。如果没有匹配的文件,大多数 shell 的默认行为是保留通配符原样。(请注意,您不能真正将通配符/模式转换为它将匹配的字符串集。星号可以匹配任何长度的任何字符串,因此扩展包含它的任何模式将产生无限的字符串列表。)
所以:
但仍然:
这两个都是由 shell 扩展的,不管你运行的命令是
ls
,echo
还是rm
. 另请注意,如果引用其中任何一个,它们将不会被扩展:{1,2,3}
(例如{1..3}
是大括号扩展。它们在命令执行之前由 shell 解释。[[:digit:]]
是一个模式匹配标记,但您没有在任何与该模式匹配的文件的位置使用它。如果您使用没有匹配项的模式匹配,它会扩展为自身: