为什么即使打开kshglob后也不能在zsh中使用!(单个模式)?


8

这在bash中有效:

touch a b c
echo !(a)

如果我在zsh(带有kshglobon)中执行以上脚本,它会抱怨:

zsh: number expected

如果我在|之后添加a,它将起作用:

echo !(a|)

为什么?

Answers:


10

因为在这种情况下,由于它位于模式的末尾,因此它与裸露的glob限定符发生冲突。*(a1)被视为最后一天中最后访问的文件。(a1)被视为全局限定符。因此,在您的!(a)情况下,zsh抱怨aglob限定符(此处适用于名为的文件!)之后缺少的天数。

zshglob中,(...)分组通常用于(foo|bar)交替,因此添加a |是有记录的方法,以确保尾部(...)不被视为glob限定符。

另一种有据可查的替代方法是将括号(!((a)))加倍,也可以添加一个空的glob限定符(如!(a)(-))。

要完全消除这种歧义,可以关闭bare_glob_qual选项(set +o bareglobqual),然后必须使用extendedglob (#q...)语法(*(#qa1)此处)编写全局限定符。

kshglob选项(在1998年添加,大约在同一时间bash添加了它,extglob尽管bash在此之前没有任何扩展的glob)主要用于ksh仿真模式(emulate ksh),以便zsh能够运行启用和禁用的ksh脚本。首次引入它时,启用后,您需要指定glob限定符,以避免这种冲突,但是会引起过多的混乱,并且与,和选项的语法相冲突。kshglobbareglobqualkshglob-(...)@-(...)ksh93(#q...)bareglobqual

zsh用户一般都喜欢的zsh自己的扩展水珠(set -o extendedglob)运算符它们更容易输入(大多数)和更强大的(除启用了ksh88者kshglob中也发现bash -O extglob)。

例如,!(foo)将被写入^foo!(foo|)bar但是,等效项将更长(^(foo|))bar

其他ksh88-> zsh翻译:

  • *(x) -> x#
  • +(x) -> x##
  • @(x|y) -> x|y
  • ?(x) -> (x|)

一些ksh93-> zsh翻译:

  • ~(i:x)-> (#i)x(不区分大小写)
  • ~(N)x-> x(N)(nullglob,起源于zsh)
  • {1,5}(x) -> x(#c1,5)
  • @(foo&bar)-> foo~^bar^(^foo|^bar)

一些只在zsh

  • <1-23> (十进制数字范围)
  • pattern~except
  • pattern(glob-qualifier) (zsh glob的杀手级功能)
  • (pattern/)#(与匹配的任何级别的子目录pattern;的**/简化版本(*/)#最近也已添加到ksh93和bash中)
  • ***/* (遵循符号链接的递归遍历)。
  • (#a1)foobar (近似匹配,允许出现一些错误,此处为1)
  • ...
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.