Bash Globbing 不符合预期

8 bash wildcards patterns

一道作业题:

匹配所有以小写字母开头但不以大写字母结尾的 2 个或更多字符的文件名。

我不明白为什么我的解决方案不起作用。

所以我执行了以下操作:

touch aa
touch ha
touch ah
touch hh
touch a123e
touch hX
touch Ax

ls [a-z]*[!A-Z]
Run Code Online (Sandbox Code Playgroud)

输出:

aa  ha
Run Code Online (Sandbox Code Playgroud)

我的问题:为什么它不匹配“ah”、“hh”或“a123e”?

xhi*_*nne 9

这是语言环境问题。在您的语言环境中,[A-Z]扩展为类似[AbBcZ...zZ](可能还有其他类似重音字符的字符),因此[^A-Z]实际上意味着a“在您的示例中以“结尾的文件(并且仅在您的示例中)。

如果您想避免这种意外,一种方法是设置,LC_COLLATE=C 因为排序规则是负责排序顺序的区域设置的一部分。此外,LC_ALL如果设置为空,则优先。

$ ls [a-z]*[^A-Z]
aa  ha

$ ( LC_ALL=; LC_COLLATE=C; ls [a-z]*[^A-Z] )
a123e  aa  ah  ha  hh
Run Code Online (Sandbox Code Playgroud)

或者,更好的是,最好不要更改您的区域设置并使用适当的类:[:lower:]代替[a-z][:upper:]代替[A-Z].

$ ls [[:lower:]]*[^[:upper:]]
a123e  aa  ah  ha  hh
Run Code Online (Sandbox Code Playgroud)

或者使用 bash 的globasciiranges选项:

$ shopt -s globasciiranges
$ ls [a-z]*[^A-Z]
a123e  aa  ah  ha  hh

$ shopt -u globasciiranges
$ ls [a-z]*[^A-Z]
aa  ha
Run Code Online (Sandbox Code Playgroud)