正则表达式 [AZ] 不识别本地字符

Sal*_*lat 0 python regex nlp

我检查了其他问题,并阅读了他们的解决方案,但它们不起作用。我已经测试了它适用于非语言环境字符的正则表达式。代码只是在字符串中找到任何大写字母并对其进行一些处理。例如minik?eker bir kedi会返回k?e但是我的代码不能识别?为[A-Z]. 当我re.LOCALE按照某些人的要求尝试ValueError: cannot use LOCALE flag with a str pattern时,使用时出现错误re.UNICODE

import re
corp = "minik?eker bir kedi"
pattern = re.compile(r"([\w]{1})()([A-Z]{1})", re.U)
corp = re.sub(pattern, r"\1 \3", corp)
print(corp)
Run Code Online (Sandbox Code Playgroud)

适用于minikSeker bir kedi不适用于minik?eker bir kedi并为 引发错误re.L。我得到的错误是ValueError: cannot use LOCALE flag with a str pattern搜索它产生了一些 git 讨论,但没有任何用处。

aba*_*ert 6

问题是?不在范围内[A-Z]。该范围是其代码点位于 U+0040 和 U+005A(含)的所有字符的类别。(如果您使用字节模式,它将是 0x40 和 0x5A 之间的所有字节。)并且?是 U+0153(或者,例如,以字节为单位的 0xAA,假设为 latin2)。不在那个范围内。

使用语言环境不会改变这一点。正如re.LOCALE解释的那样,它所做的就是:

使 \w、\W、\b、\B 和不区分大小写的匹配依赖于当前的语言环境。

此外,您几乎从不想使用re.LOCALE. 正如文档所说:

不鼓励使用此标志,因为区域设置机制非常不可靠,它一次只处理一种“文化”,并且仅适用于 8 位区域设置。

如果您只关心单个脚本,则可以为该脚本构建一个具有适当范围的类。

如果要使用所有脚本,则需要使用 Unicode 字符类构建一个类,例如Lu“所有大写字母”。不幸的是,Pythonre没有直接执行此操作的机制。您可以根据 中的信息构建一个巨大的类unicodedata,但这很烦人:

Lu = '[' + ''.join(chr(c) for c in range(0, 0x10ffff) 
                   if unicodedata.category(chr(c)) == 'Lu') + ']'
Run Code Online (Sandbox Code Playgroud)

进而:

pattern = re.compile(r"([\w]{1})()(" + Lu + r"{1})", re.U)
Run Code Online (Sandbox Code Playgroud)

… 或者可能:

pattern = re.compile(rf"([\w]{{1}})()({Lu}{{1}})", re.U)
Run Code Online (Sandbox Code Playgroud)

但好消息是,re没有任何方法指定 Unicode 类的部分原因是,长期以来,计划是re用新模块替换,因此许多建议的新功能re被拒绝。但好消息是,预期的新模块可作为第三方库使用,regex. 它工作得很好,并且几乎可以替代re; 它只是改进得太快了,无法将其锁定到较慢的 Python 发布时间表。如果你安装它,那么你可以这样写你的代码:

import regex
corp = "minik?eker bir kedi"
pattern = regex.compile(r"([\w]{1})()(\p{Lu}{1})", re.U)
corp = regex.sub(pattern, r"\1 \3", corp)
print(corp)
Run Code Online (Sandbox Code Playgroud)

我所做的唯一更改是替换re为regex,然后使用\p{Lu}代替[A-Z]。

当然,还有许多其他正则表达式引擎,其中许多还支持 Unicode 字符类。大多数都遵循相同\p语法的一些变化。(他们都从 Perl 复制了它,但细节不同——例如,regexUnicode 类的想法来自unicodedata模块,而PCRE并PCRE2试图尽可能接近 Perl,等等。)