这在 bash 中有效:
touch a b c
echo !(a)
如果我在 zsh 中执行上面的脚本(打开kshglob
),它会抱怨:
zsh: number expected
如果我|
在之后添加a
,它会起作用:
echo !(a|)
为什么?
答案1
因为在这种情况下,它与裸 glob 限定符因为它位于模式的末尾。*(a1)
被视为最近一天最后访问的文件。(a1)
被视为全局限定符。因此,在您的!(a)
情况下,zsh 抱怨 glob 限定符后缺少天数a
(此处应用于名为 的文件!
)。
在zsh
glob 中,(...)
分组主要用于(foo|bar)
交替,因此添加 a|
是一种记录在案的方法,以确保尾随(...)
不被视为 glob 限定符。
另一种记录在案的替代方法是双括号 ( !((a))
) 或者您可以添加一个空的 glob 限定符(如!(a)(-)
)。
要完全消除这种歧义,可以关闭bare_glob_qual
选项 ( set +o bareglobqual
),之后必须使用语法extendedglob
(#q...)
(*(#qa1)
此处)编写 glob 限定符。
选项kshglob
(1998年添加,大约在同一时间bash
添加了它,extglob
尽管 bash 在此之前没有任何扩展的 glob)主要用于ksh
模拟模式(emulate ksh
),以便zsh
能够运行ksh
脚本,其中kshglob
启用和bareglobqual
禁用。首次引入时,启用 后kshglob
,您需要指定 glob 限定符以-(...)
避免此类冲突,但这会导致太多混乱,并与@-(...)
的语法发生冲突ksh93
,之后引入了(#q...)
和选项。bareglobqual
zsh
用户通常更喜欢 zsh 自己的扩展 glob ( set -o extendedglob
) 运算符,它更容易键入(对于大多数人来说)并且功能更强大(比kshglob
中也启用的 ksh88 运算符更强大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)- ...