我想问:
为什么echo {1,2,3}
扩展到 1 2 3 这是预期的行为,而echo [[:digit:]]
返回[[:digit:]]
而我希望它打印所有数字从0
to 9
?
ter*_*don 34
因为它们是两种不同的东西。这{1,2,3}
是大括号扩展的一个例子。该{1,2,3}
结构扩大由外壳,之前echo
甚至看到它。如果您使用,您可以看到会发生什么set -x
:
$ set -x
$ echo {1,2,3}
+ echo 1 2 3
1 2 3
Run Code Online (Sandbox Code Playgroud)
如您所见,该命令echo {1,2,3}
扩展为:
echo 1 2 3
Run Code Online (Sandbox Code Playgroud)
然而,[[: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
Run Code Online (Sandbox Code Playgroud)
如果 glob 确实匹配某些内容,则将打印:
$ echo /e*c
+ echo /etc
/etc
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,echo
只打印 shell 告诉它打印的任何内容,但在第二种情况下,由于 glob 匹配某些内容 ( /etc
),它被告知打印该内容。
因此,由于您没有任何名称仅由一位数字组成的文件或目录(这是[[:digit:]]
匹配的数字),因此 glob 将扩展为自身,您将得到:
$ echo [[:digit:]]
[[:digit:]]
Run Code Online (Sandbox Code Playgroud)
现在,尝试创建一个名为的文件5
并运行相同的命令:
$ echo [[:digit:]]
5
Run Code Online (Sandbox Code Playgroud)
如果有多个匹配文件:
$ touch 1 5
$ echo [[:digit:]]
1 5
Run Code Online (Sandbox Code Playgroud)
这(有点)记录在关闭此行为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.
Run Code Online (Sandbox Code Playgroud)
如果设置此选项:
$ rm 1 5
$ shopt -s nullglob
$ echo [[:digit:]] ## prints nothing
$
Run Code Online (Sandbox Code Playgroud)
ilk*_*chu 14
{1,2,3}
是大括号扩展,它扩展到列出的单词而不考虑它们的含义。
[...]
是一个字符组,用于文件名扩展(或通配符或通配符),类似于星号*
和问号?
。它匹配其中列出的任何单个字符,或作为命名组成员的字符(例如,[: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
Run Code Online (Sandbox Code Playgroud)
但仍然:
$ bash -c 'echo {1,2,3}'
1 2 3
Run Code Online (Sandbox Code Playgroud)
这两个都由 shell 展开,您运行的命令是ls
, 或echo
或都没有关系rm
。另请注意,如果引用其中任何一个,它们将不会被扩展:
$ bash -c 'echo "[[:digit:]]"' # even though matching files still exist
[[:digit:]]
$ bash -c 'echo "{1,2,3}"'
{1,2,3}
Run Code Online (Sandbox Code Playgroud)