Python Regex[A-Z]无法识别本地字符

Python Regex[A-Z]无法识别本地字符,python,regex,nlp,Python,Regex,Nlp,我检查了其他问题,并阅读了它们的解决方案,它们不起作用。我已经测试了正则表达式,它在非语言环境字符上工作。代码就是简单地找到字符串中的任何大写字母,并对它们执行一些过程。例如minikŞeker bir kedi将返回kŞe,但是我的代码不将Ş识别为[a-Z]中的字母。当我按照一些人的要求尝试re.LOCALE时,我得到错误ValueError:当我使用re.UNICODE import re corp = "minikŞeker bir kedi" pattern = re.compile(r

我检查了其他问题,并阅读了它们的解决方案,它们不起作用。我已经测试了正则表达式,它在非语言环境字符上工作。代码就是简单地找到字符串中的任何大写字母,并对它们执行一些过程。例如
minikŞeker bir kedi
将返回
kŞe
,但是我的代码不将
Ş
识别为
[a-Z]
中的字母。当我按照一些人的要求尝试
re.LOCALE
时,我得到错误
ValueError:当我使用
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)

适用于
minikSeker-bir-kedi
不适用于
minikŞeker-bir-kedi
并为
re.L
抛出错误。我得到的错误是
ValueError:cannotuse LOCALE flag with The str pattern
搜索它产生了一些git讨论,但没有任何用处。

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

使用区域设置不会改变这一点。正如所解释的,它所做的只是:

使\w、\w、\b、\b和不区分大小写的匹配依赖于当前区域设置

而且,您几乎不想使用
re.LOCALE
。正如文件所说:

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

若您只关心一个脚本,那个么可以为该脚本构建一个具有适当范围的类

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

Lu = '[' + ''.join(chr(c) for c in range(0, 0x10ffff) 
                   if unicodedata.category(chr(c)) == 'Lu') + ']'
然后:

pattern = re.compile(r"([\w]{1})()(" + Lu + r"{1})", re.U)
……或者:

pattern = re.compile(rf"([\w]{{1}})()({Lu}{{1}})", re.U)

但好消息是,
re
无法指定Unicode类的部分原因是,很长一段时间以来,计划用一个新模块替换
re
,因此许多建议的
re
新功能被拒绝。但好消息是,预期的新模块作为第三方库提供。它工作正常,几乎可以替代
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)
我所做的唯一更改是将
re
替换为
regex
,然后使用
\p{Lu}
而不是
[A-Z]


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

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

使用区域设置不会改变这一点。正如所解释的,它所做的只是:

使\w、\w、\b、\b和不区分大小写的匹配依赖于当前区域设置

而且,您几乎不想使用
re.LOCALE
。正如文件所说:

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

若您只关心一个脚本,那个么可以为该脚本构建一个具有适当范围的类

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

Lu = '[' + ''.join(chr(c) for c in range(0, 0x10ffff) 
                   if unicodedata.category(chr(c)) == 'Lu') + ']'
然后:

pattern = re.compile(r"([\w]{1})()(" + Lu + r"{1})", re.U)
……或者:

pattern = re.compile(rf"([\w]{{1}})()({Lu}{{1}})", re.U)

但好消息是,
re
无法指定Unicode类的部分原因是,很长一段时间以来,计划用一个新模块替换
re
,因此许多建议的
re
新功能被拒绝。但好消息是,预期的新模块作为第三方库提供。它工作正常,几乎可以替代
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)
我所做的唯一更改是将
re
替换为
regex
,然后使用
\p{Lu}
而不是
[A-Z]


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

abarnet的答案很好,但如果您只想找到大写字符,
str.isupper()
在没有