Регулярное выражение Python \ w не соответствует сочетанию диакритических знаков? - PullRequest
9 голосов
/ 29 июня 2010

У меня есть строка UTF8 с сочетанием диакритических знаков.Я хочу сопоставить его с последовательностью регулярных выражений \w.Это соответствует символам, которые имеют акценты, но нет, если есть латинский символ с объединяющими диакритическими знаками.

>>> re.match("a\w\w\wz", u"aoooz", re.UNICODE)
<_sre.SRE_Match object at 0xb7788f38>
>>> print u"ao\u00F3oz"
aoóoz
>>> re.match("a\w\w\wz", u"ao\u00F3oz", re.UNICODE)
<_sre.SRE_Match object at 0xb7788f38>
>>> re.match("a\w\w\wz", u"aoo\u0301oz", re.UNICODE)
>>> print u"aoo\u0301oz"
aóooz

(Похоже, что процессор уценки SO испытывает проблемы с объединением диакритических знаков в приведенном выше,в последней строке есть символ ́)

Можно ли сопоставить сочетание диакритических знаков с \w?Я не хочу нормализовать текст, потому что этот текст взят из имени файла, и я пока не хочу выполнять полную «нормализацию имени файла в Юникоде».Это Python 2.5.

Ответы [ 2 ]

6 голосов
/ 06 июля 2010

Я только что заметил новый пакет " regex " на pypi.(если я правильно понимаю, это тестовая версия нового пакета, который когда-нибудь заменит пакет stdlib re).

Кажется, у него есть (помимо прочего) больше возможностей в отношении юникода.Например, он поддерживает \X, который используется для сопоставления одной графемы (использует ли она объединение или нет).Он также поддерживает сопоставление свойств юникода, блоков и сценариев, поэтому вы можете использовать \p{M} для ссылки на метки объединения.\X, упомянутый ранее, эквивалентен \P{M}\p{M}* (символ, который НЕ является знаком объединения, за которым следует ноль или более знаков объединения).

Обратите внимание, что это делает \X более или менее эквивалентом Юникода.., а не \w, так что в вашем случае \w\p{M}* - это то, что вам нужно.

Это (пока) пакет не-stdlib, и я не знаю, насколько готовэто так (и оно не входит в бинарный дистрибутив), но вы можете попробовать, так как это кажется самым простым / наиболее «правильным» ответом на ваш вопрос.(в противном случае, я считаю, что вам следует явно использовать диапазоны символов, как описано в моем комментарии к предыдущему ответу).

См. также эту страницу с информацией о регулярных выражениях Юникода, которая такжесодержит некоторую полезную информацию для вас (и может служить документацией для некоторых вещей, реализованных в пакете regex).

2 голосов
/ 29 июня 2010

Вы можете использовать unicodedata.normalize , чтобы объединить объединяющие диакритические знаки в один символ Unicode.

>>> import re
>>> from unicodedata import normalize
>>> re.match(u"a\w\w\wz", normalize("NFC", u"aoo\u0301oz"), re.UNICODE)
<_sre.SRE_Match object at 0x00BDCC60>

Я знаю, что вы сказали, что не хотите нормализовать, но я не думаю, что с этим решением возникнет проблема, так как вы только нормализуете строку для сравнения и вам не нужно менять имя файла сам или что-то.

...