Bash 和 Zsh 如何处理模式和正则表达式中的排序规则?

Bash 和 Zsh 如何处理模式和正则表达式中的排序规则?

考虑以下示例:

$ bash --version
GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ LC_COLLATE=C bash --norc -c '[[ B == [a-z] ]] && echo yes || echo no'
no
$ LC_COLLATE=en_GB bash --norc -c '[[ B == [a-z] ]] && echo yes || echo no'
yes
$ LC_COLLATE=C bash --norc -c '[[ B =~ [a-z] ]] && echo yes || echo no'
no
$ LC_COLLATE=en_GB bash --norc -c '[[ B =~ [a-z] ]] && echo yes || echo no'
no

似乎在匹配时图案(即使用=or ==),Bash 根据 LC_COLLATE 进行整理;然而,当与正则表达式匹配时(即使用=~),Bash 根据 POSIX 或类似的东西进行整理。

Zsh——至少——在所有情况下zsh 5.8.0.2-dev (x86_64-pc-linux-gnu)都会打印。no

[a-z]在模式或正则表达式中使用时,是否能保证准确匹配的内容?

答案1

不,不能保证到底[a-z]会匹配什么,就这样。

好吧,在任何其他语言环境中"C"(当实用程序符合 POSIX 时)。

核心问题在于“范围”表达式(使用-)。
像这样的明确列表[abcdefghijklmnopqrstuvwxyz]永远不会失败。


POSIX 请求正是a-zabcdefghijklmnopqrstvwxyz是的,但仅当区域设置是 POSIX 默认值时,即:"C"

来自 POSIX 规范:

在 POSIX 语言环境中,范围表达式表示位于排序规则序列中两个元素之间(包括这两个元素)的排序元素集。在其他语言环境中,范围表达式具有未指定的行为:严格遵守的应用程序不应依赖于范围表达式是否有效,或匹配的整理元素集。范围表达式应表示为用('-')分隔的起点和终点。

即使 POSIX 请求特定含义,a-z任何应用程序也可能选择简单地忽略 POSIX。

只是为了展示冰山一角:

Python 2.7 仅匹配 ASCII,a-z但 Python 3.0 将匹配许多其他 Unicode 字符。 Bash 过去仅匹配 3.2 版之前的 ASCII。然后它决定匹配的字符整理a和之间,在应用的区域设置中z可能包括A-Y(通常不包括)。Z现在,在 bash 版本 5.0+ 中,可以使用 globasciiranges 选项来配置范围,该选项是默认情况下,使a-z意图匹配大多ASCII 字符。

$ LC_COLLATE=en_GB bash -c 'shopt -u globasciiranges; [[ B == [a-z] ]] && echo yes || echo no'
yes

$ LC_COLLATE=en_GB bash -c 'shopt -s globasciiranges; [[ B == [a-z] ]] && echo yes || echo no'
no

但即使 bash 5.0 和 globasciiranges 处于活动状态,也== [a-z]将匹配 en_GB.utf-8 语言环境中的 2190 个字符。仅供您理解,这是a允许的类似字符的列表:

a a ͣ ⒜ 

相关内容