Проблема в том, что Ş
не находится в диапазоне [A-Z]
. Этот диапазон является классом всех символов, чьи кодовые точки лежат U + 0040 и U + 005A (включительно). (Если бы вы использовали байтовый режим, все байты были бы в диапазоне от 0x40 до 0x5A.) И Ş
- это U + 0153 (или, например, 0xAA в байтах, при условии latin2). Который не в этом диапазоне.
И использование локали не изменит этого. Как объясняет re.LOCALE
, все, что он делает, это:
Сделать \ w, \ W, \ b, \ B и сопоставление без учета регистра зависимым от текущей локали.
Кроме того, вы почти никогда не хотите использовать re.LOCALE
. Как говорят в документах:
Использование этого флага не рекомендуется, поскольку механизм локали очень ненадежен, он обрабатывает только одну «культуру» за раз и работает только с 8-битными локалями.
Если вам нужен только один сценарий, вы можете создать класс соответствующих диапазонов для этого сценария.
Если вы хотите работать со всеми сценариями, вам нужно создать класс из класса символов Unicode, например Lu
для "всех заглавных букв". К сожалению, у re
в Python нет механизма, позволяющего делать это напрямую. Вы можете создать гигантский класс из информации в 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
были отклонены. Но хорошая новость заключается в том, что предполагаемый новый модуль доступен в виде сторонней библиотеки, 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)
Единственное изменение, которое я сделал, - заменить re
на regex
, а затем использовать \p{Lu}
вместо [A-Z]
.
Конечно, существует множество других движков регулярных выражений, и многие из них также поддерживают классы символов Юникода. Большинство из тех, которые следуют некоторым вариациям в том же синтаксисе \p
. (Все они скопировали его из Perl, но детали отличаются - например, идея regex
о классах Unicode происходит из модуля unicodedata
, в то время как PCRE
и PCRE2
пытаются быть как можно ближе к Perl, и тд.)