ZSH 通配符表达式限制重复支持?

ZSH 通配符表达式限制重复支持?

有谁知道是否有办法将重复约束合并到 ZSH 通配符表达式中?

例如,要匹配以“ABC”开头后跟一个或多个数字的所有文件,可以使用 grep one 执行以下操作:

ls | grep -e "ABC[0-9]\+"

有没有办法直接使用 ZSH glob 字符串来执行此操作?大致如下:

ls "ABC[0-9]\+"

我已经浏览过ZSH 文档并用谷歌搜索类似的东西,但到目前为止还没有找到任何这样的支持。

有人知道这是否可能吗?

答案1

是的,用于##匹配一个或多个出现的[0-9]like:

ABC[0-9]##

这个需要extendedglob设置,默认即可。如果未设置,请先设置:

setopt extendedglob

例子:

% print -l ABC*
ABC
ABC75475
ABC8
ABC90

% print -l ABC[0-9]##
ABC75475
ABC8
ABC90

答案2

向下滚动到“文件名生成”,并启用extended_glob(这应该是默认值,但不是为了向后兼容)或ksh_glob。 zsh 的扩展 glob 和 ksh 都具有正则表达式的全部功能。

ERE syntax      ksh glob      zsh extended glob
(foo)*          *(foo)        (foo)#
(foo)+          +(foo)        (foo)##
(foo)?          ?(foo)        (|foo)
(foo|bar)       @(foo|bar)    (foo|bar)

请记住,大多数使用正则表达式的工具都将它们用作搜索必须匹配子字符串的模式,但 glob 始终用作必须匹配整个字符串的模式。例如,与foofoobarzsh glob 不匹配(foo)##,因为之后foofoo留下了一些文本。

Zsh 有额外的运算符,这些运算符不会扩展表达能力,但使某些表达式更易于编写。运算符^and ~( extended_glob) 和!(…)( ksh_glob) 提供否定,例如^fooor!(foo)匹配除 之外的任何内容foo,这在正则表达式语法中需要笨重的|[^f].*|f[^o].*|fo[^o].*.运算符<…-…>(zsh 特定的,不需要extended_glob)匹配某个范围内的任何整数(以十进制表示),例如<3-11>匹配3and10但不匹配30or 1

因此,排除诸如无法打印字符之类的问题,ls | grep -e "ABC[0-9]\+"可以用以下方式编写

print -lr -- *ABC[0-9]##*(N)      # requires extended_glob
print -lr -- *ABC+([0-9])*(N)      # requires ksh_glob
print -lr -- *ABC+<->(N)

但由于“一个或多个数字然后任何内容”相当于“一个数字然后任何内容”,所以也可以写成

print -lr -- *ABC[0-9]*(N)

答案3

启用后extendedglob

$ setopt extendedglob
$ print -rl -- perl[[:digit:]]##
perl5

kshglob启用和bareglobqual禁用:

$ setopt kshglob
$ unsetopt bareglobqual
$ print -rl -- perl+([[:digit:]])
perl5

请注意,用于[:digit:]匹配当前区域设置中所有被视为数字的内容。如果您只想匹配09请设置LC_ALL=C或使用字面意思[0123456789]


您可以指定匹配的数量,例如在可以使用和运算符的任何地方{n,m}使用(#cN,M)globbing 标志的正则表达式,除了 in和:###(*/)#(*/)##

$ print -rl -- perl[[:digit:]](#c1)
perl5
$ print -rl -- perl[[:digit:]](#c2)
zsh: no matches found: perl[[:digit:]](#c2)

相关内容