有人可以解释一下为什么 Korn shell 中的模式(分配给变量)这样工作:
u@h:w$ pattern='file_[0-9][0-9]'
u@h:w$ ls $pattern
file_01 file_02 file_03
但它不适用于更智能的模式file_{2}([0-9])
:
$ pattern='file_{2}([0-9])'
$ ls $pattern
ls: file_{2}([0-9]): No such file or directory
答案1
这是有意为之,以避免破坏 POSIX 合规性(尽管最初是为了避免破坏 Bourne 兼容性)。
echo file_{2}([0-9])
在 Bourne/POSIX 中将是无效代码sh
,因此ksh
可以随意解释它。但:
pattern='file_{2}([0-9])'
echo $pattern
是有效的 Bourne/POSIXsh
代码,并且根据 POSIX,旨在匹配名为file_{2}(0)
, file_{2}(1)
...的文件
当扩展运算符是扩展的结果时,它们不可用,即使您使用:
echo @($pattern)
您需要使用eval
,或者您也可以使用FIGNORE
:
FIGNORE="!($pattern)"; echo *
(请注意,它会影响隐藏文件的扩展,FIGNORE="@(.*|!($pattern))"
如果您不希望 glob 扩展隐藏文件,请进行此操作)。
请注意,bash
后来zsh
采用了其中一些ksh
扩展运算符(尽管不是唯一{x,y}(...)
的),但它们以不同的方式解决了 POSIX 合规性/Bourne 兼容性:它们使这些扩展 glob 在所有上下文中都可用,但仅在启用特定选项时(kshglob
in zsh
、extglob
in bash
)。然而,这意味着他们很难在不破坏自己的向后兼容性的情况下添加更多运算符。例如,如果现在bash
添加运算符,它可能会破坏期望返回 true 的{x,y}(...)
脚本。a='{1}(2){3}'; [[ $a = $a ]]