Answers:
因为它们是两个不同的东西。这{1,2,3}
是括号扩展的示例。该{1,2,3}
结构由shell扩展,echo
甚至看不到它。您可以查看使用set -x
以下方法会发生什么:
$ set -x
$ echo {1,2,3}
+ echo 1 2 3
1 2 3
如您所见,命令echo {1,2,3}
扩展为:
echo 1 2 3
但是,[[:digit:]]
是POSIX字符类。当您提供给它时echo
,shell也会首先对其进行处理,但是这次将其作为shell glob处理。它的运行方式与您运行时echo *
将打印当前目录中所有文件的方式相同。但是,它[[:digit:]]
是一个可以匹配任何数字的Shell Glob。现在,在bash中,如果shell glob不匹配任何内容,它将扩展为自身:
$ echo /this*matches*no*files
+ echo '/this*matches*no*files'
/this*matches*no*files
如果glob确实与某项匹配,则将进行打印:
$ echo /e*c
+ echo /etc
/etc
在这两种情况下,echo
都只打印外壳告诉它要打印的内容,而在第二种情况下,由于glob匹配某物(/etc
),因此它被告知要打印该东西。
因此,由于您没有名称完全由一位数字组成的文件或目录([[:digit:]]
将与之匹配),因此将全局扩展为自身,您将得到:
$ echo [[:digit:]]
[[:digit:]]
现在,尝试创建一个名为5
并运行相同命令的文件:
$ echo [[:digit:]]
5
并且如果有多个匹配文件:
$ touch 1 5
$ echo [[:digit:]]
1 5
man bash
在nullglob
选项的说明中记录了这种情况(这些情况),该选项可以关闭此行为:
nullglob
If set, bash allows patterns which match no files (see
Pathname Expansion above) to expand to a null string,
rather than themselves.
如果设置此选项:
$ rm 1 5
$ shopt -s nullglob
$ echo [[:digit:]] ## prints nothing
$
shopt -s failglob
以获取类似于现代外壳(如zsh
或)的更有用的行为fish
。
failglob
。nullglob
可能会导致意外问题,例如,粘贴恰好具有的URL时?
。
nullglob
要说明该模式被shell解释为glob。
{1,2,3}
是大括号扩展,不考虑其含义扩展为列出的单词。
[...]
是一个字符组,用于文件名扩展(或通配符或glob),类似于星号*
和问号?
。它与其中列出的任何单个字符或作为命名组成员的字符(例如[:digit:]
列出的那些字符)匹配。大多数shell的默认行为是,如果没有与之匹配的文件,则按原样保留通配符。
(请注意,您不能真正将通配符/模式转换为它将匹配的字符串集。星号可以匹配任何长度的任何字符串,因此扩展包含它的任何模式将产生无限的字符串列表。)
所以:
$ 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
但仍然:
$ bash -c 'echo {1,2,3}'
1 2 3
两者都由shell扩展,无论您运行的命令是ls
还是echo
or 都没关系rm
。另请注意,如果引用了其中任何一个,则将不会对其进行扩展:
$ bash -c 'echo "[[:digit:]]"' # even though matching files still exist
[[:digit:]]
$ bash -c 'echo "{1,2,3}"'
{1,2,3}
[[:digit:]]
在传递给之前先对其进行“扩展” echo
,所以echo
永远不会看到[[:digit:]]
,只能看到1 3
。您可以通过运行查看set -x
实际运行情况,该命令将打印正在运行的实际命令(运行set +x
以再次将其关闭)。
echo
,shell不会查找文件echo
。
{1,2,3}
(例如,{1..3}
是括号扩展。它们在命令执行之前由外壳程序解释。
[[:digit:]]
是与模式匹配的令牌,但是您没有在与该模式匹配的任何文件的位置使用它。如果您使用没有匹配项的模式匹配项,它将扩展为自身:
$ echo [[:digit:]]; touch 3; echo [[:digit:]]
[[:digit:]]
3