为什么在zsh中使用{1..9}会出现错误?

9
我运行了以下代码。
zgrep -c compinit /usr/share/man/man{1..9}/zsh*

我明白了

zsh: no matches found: /usr/share/man/man2/zsh*

这很奇怪,因为以下内容是有效的

echo Masi{1..9}/masi

这让我觉得问题可能是Zsh的一个bug。

上述问题是否是针对{1..9}的Zsh bug?

2个回答

11
在zsh中,如果您想在文件名中使用范围,zle可以对其可以扩展的任何实际名称提供<1-n>。也就是说:
$ touch a0b a1b a5b a7b
$ print a<0-100>b

在最后一个b后面按下<Tab>键将展开一行中的print a0b a1b a5b a7b

除此之外,也可以使用zsh循环表达式来实现其他需求,如全范围要求、非文件和脚本使用:

for n ({1..50}); do print $n; done

将允许您处理从1到50的整个序列范围 :) 然后您可以使用各种有用的方法,例如一个尚不存在的文件集合:

arr=($(for n ({1..50}); do print /my/path/file$n.txt; done)) && print $arr[33]

11

这不是一个 bug,而且在单词内部工作得很好。你在这里遇到的问题是 {1..9} 不像 * 一样是通配符表达式;正如你的 echo 示例所示,它是一个迭代扩展。所以你的 zgrep 示例与你在命令行中输入每个交替版本是完全相同的,并且由于没有以 zsh 开头的 man 页面在 man2 中,因此会出现错误。(它在查找匹配项失败时报错,与大括号序列扩展本身无关。)

另一方面,如果你执行以下操作:

zgrep -c compinit /usr/share/man/man[1-9]/zsh*

你会得到你期望的结果,因为 [1-9] 是一个正常的通配符表达式。


所以我们有两个空间:一个是非通配符空间,另一个是通配符空间。如果存在一个通配符,它会强制我只使用通配符字符。同样地,你只能单独使用非通配符字符。- - 感谢您的回答! - Léo Léopold Hertz 준영
2
@Masi:不完全正确。如果我有一个目录,其中包含1-hello.gif,2-world.gif,...,20-foobar.gif,{1..20}-*.gif将完美地匹配它们,而[1-20]-*.gif仅匹配前两个。但是,如果任何连续编号的文件丢失,这将导致与您问题中相同的错误。 - ephemient
@ephemient:你的意思是说如果没有7File这样的文件,[1-20]File就无法工作?-- 如果是这样,那么使用[1-20]有什么好处呢?相比之下,{1..20}并不会导致这个问题。 - Léo Léopold Hertz 준영
@Masi:他的意思是[1-20]不是指从一到二十,而是和[120]一样,即可以是1、2或0中的任何一个。[]中的范围功能只适用于从一个字符到另一个字符的范围,比如A-Z、a-z、0-9。它不能处理像1-20这样的范围;对于这些情况,您需要进行其他操作。 - chaos
[](组)符号基本上与常见的正则表达式中的相同;同样的限制也适用。 - dom0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接