正则表达式 [A-Za-z] 似乎不包含字母 W 和 w

2024-03-24

由于某种原因,我不知道为什么,也许我的系统或我的大脑有些不对劲,正则表达式“[A-Z]”似乎无法识别字母“W”和“[a-z]” ” 似乎不认识字母“w”。例子:

for x in A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Y y Z z; do echo $x | egrep "[A-Za-z]"; done

我的输出是: A A 乙 乙 C C D d 乙 e F F G G H H 我 我 J j K k L 我 中号 米 氮 n 氧 哦 磷 p 问 q 右 r S s 时间 t U 你 V v X X 是 y Z z

正如您所看到的,字母“W”和“w”都丢失了。我是唯一一个?什么可能导致这种情况?如果是错误,我应该在哪里报告?这种情况发生在 bash 和 zsh 中,也发生在 sed 和 egrep 中(可能还有更多,我只测试了这两个),所以问题似乎与一般的正则表达式有关......:o 那么发生了什么??

  • 曼扎罗 17.1.12
  • XFCE 4.12
  • bash 4.4.23(1)-发布(x86_64-未知-linux-gnu)
  • zsh 5.5.1(x86_64-未知-linux-gnu)
  • egrep 3.1
  • sed 4.5

编辑:有人询问我的区域设置,所以就在这里。

$ locale        
LANG=sv_SE.utf8
LC_CTYPE="sv_SE.utf8"
LC_NUMERIC=sv_SE.UTF-8
LC_TIME=sv_SE.UTF-8
LC_COLLATE="sv_SE.utf8"
LC_MONETARY=sv_SE.UTF-8
LC_MESSAGES="sv_SE.utf8"
LC_PAPER=sv_SE.UTF-8
LC_NAME=sv_SE.UTF-8
LC_ADDRESS=sv_SE.UTF-8
LC_TELEPHONE=sv_SE.UTF-8
LC_MEASUREMENT=sv_SE.UTF-8
LC_IDENTIFICATION=sv_SE.UTF-8
LC_ALL=

如果这是问题所在,那么我想无论决定什么是 sv_SE.UTF-8 ,都是错误的,因为字母“w”于 2006 年被添加到瑞典字母表中。 另外,如果 A-Z 间隔取决于当前区域设置,那么当区域设置设置为瑞典语时,[A-Ö] 不应该适用于整个瑞典字母表吗?没有,它会给出错误消息。然而 [[:alpha:]] 似乎包含所有瑞典语字母,所以我想我对此感到满意。


从技术上讲,使用范围表达式,例如[a-z]Posix 正则表达式(与 grep 实用程序一样)中仅在 Posix (C) 语言环境中具有指定行为。这意味着您确实无法可靠地在sv_SE语言环境(或任何其他国际化语言环境)。但是,您可以可靠地使用字符类,例如[[:lower:]], [[:alpha:]], [[:alnum:]]等等,这通常是您应该做的。

话虽如此,我相信您遇到的情况确实是 v2.28 中引入的 glibc 中的一个错误,因为以前的版本sv_SE区域设置正确放置w在小写范围内和W在大写范围内。我认为这一更改不符合用户的期望,因为它会破坏以前尽管具有未指定行为但仍按预期工作的正则表达式范围表达式。

大约一个月前,该问题被报告为 glibc bug,并且几乎立即因缺乏文档而关闭;昨天我要求重新开放 https://sourceware.org/bugzilla/show_bug.cgi?id=23447#c4. (Update:该错误被重新认定为另一个错误的重复,其最终解决方案只能是底层设计问题的全面解决方案。换句话说,glibc 团队知道存在问题,但不会屏息以待解决方案。)

我已经放置了一个可能的替代品sv_SE语言环境定义文件位于这个存储库 https://github.com/ricilake/locales,以防它被证明对某人有用。除非您遇到 glibc 的语言环境定义问题,否则请不要安装它。

我在上面链接的错误报告中过长的评论试图阐明问题,这更多的是定义问题而不是实现问题。本质问题是定义一个与整个字符串比较顺序完全一致的单字符排序顺序是非常困难的(如果不是不可能的话)。阅读 Posix 基本原理文档的字里行间,似乎很明显,很多人都在用头撞这堵特定的砖墙,却从未设法提出一个具有实施共识的实用可移植提案。 (“如上所述,我们已努力解决这些差异,但尚未找到足够具体的解决方案来允许可移植软件,同时又不会使现有实现失效。”)

对各种区域设置定义文件的善意清理导致瑞典区域设置中的字符顺序发生更改。它没有改变字符串排序顺序,因此V and W继续像以前一样排序(也就是说,就好像它们是同一字母而不是不同字母的变体拼写),并且它没有改变 CTYPE 定义,因此W and w继续是字母(因此匹配[[:alpha:]])和以前一样。但它确实(我相信是偶然的)改变了字符顺序。前,W已关注V and w已关注v, 以便W匹配的[U-X] and w匹配的[u-x]。此更改将两个字符放置在 thorn (þ) 之后,这意味着它无法匹配任何范围表达式。 (正则表达式范围表达式仅限于单字节代码点。)


A 上一个问题 https://stackoverflow.com/questions/11925537/should-we-consider-using-range-a-z-as-a-bug已被建议作为此问题的重复项,但我删除了重复标记,因为该问题侧重于使用的智慧[a-z]而不是可能的实现错误,而且还因为它是关于 Perl 正则表达式而不是 Posix 正则表达式。不过,答案中有很多有用的信息。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

正则表达式 [A-Za-z] 似乎不包含字母 W 和 w 的相关文章

随机推荐