UTF — символы в регулярных выраженияж

229 просмотра
0

в регулярных выражениях можно вставлять символы по их кодам вот так \x20

Но я не могу понять как там использовать четырёхзначные коды символов, например \u2011работает в простых строках, но не работает в регулярках.

Кто знает как в python без костылей писать 4-значные коды символов в регулярках?


Добавить комментарий

2 Answers

Python Опубликовано 14.12.2018
0

Данные коды можно использовать без проблем в обычных строковых литералах.

def link_conjunctions_with_words(text):
    return sub(r'\s+([\wА-Яа-я]{1,2})\s+', r' \1' + '\u00A0', text)
                                                    ^

Или

def link_conjunctions_with_words(text):
    return sub(r'\s+([\wА-Яа-я]{1,2})\s+', ' \\1\u00A0', text)
                                           ^

См. испраленное демо

Следите за тем, как вы объявляете обратный слеш:

'\1' = 1 символ SOH (символ с кодом \x01)
'\\1' = r'\1' = 2 символа, \ и 1 (обратная ссылка в регулярках)

Добавить комментарий
0

r'' это не регулярное выражение, это raw string literal (вид строковых констант)—внутри таких констант \X заменяется на \X для любого X. То есть, если backslash не последний символ в константе, то он как-будто не имеет специального смысла (в отличии от обычных строковых констант '') и как есть вставляется.

Дополнительно, если константа используется чтобы задать регулярное выражение, то backslash дважды интерпретируется. К примеру, '\1' создаёт строку с одним Unicode символом U+0001. Если эту строку как регулярное выражение интерпретировать, то оно буквально совпадает с U+0001 символом:

>>> import re
>>> re.match('\1', '\u0001')
<_sre.SRE_Match object; span=(0, 1), match='\x01'>

Чтобы regex движок увидел backslash здесь, его необходимо экранировать в строке:

>>> '\\1' == r'\1'
True
>>> re.match('\\1', '\u0001')
Traceback (most recent call last):
...
sre_constants.error: invalid group reference 1 at position 1

В этом случае константа создаёт строку из двух символов U+005C и U+0031, которые распознаются движком как ссылка на первую [несуществующую в примере] группу в regex.

Если вы напишите, r'\u0061', то создаётся строка из 6 символов, что естественно отличается от '\u0061' (один символ).

Регулярное выражение можно задать как с помощью самого символа так и экранированной последовательности:

>>> re.match('\\u0061', 'a')
<_sre.SRE_Match object; span=(0, 1), match='a'>
>>> re.match('\u0061', 'a')
<_sre.SRE_Match object; span=(0, 1), match='a'>

Поэтому работают все варианты:

>>> re.match('[\u0060-\u0065]', 'a')
<_sre.SRE_Match object; span=(0, 1), match='a'>
>>> re.match(r'[\u0060-\u0065]', 'a')
<_sre.SRE_Match object; span=(0, 1), match='a'>
>>> re.match('[\\u0060-\\u0065]', 'a')
<_sre.SRE_Match object; span=(0, 1), match='a'>

В подстановочной строке, \u последовательность не распознаётся regex движком, поэтому сам символ приходится использовать:

>>> re.sub('([\u0060-\u0065])', '\\1b', 'a a')
'ab ab'
>>> re.sub('([\u0060-\u0065])', '\\1\u0062', 'a a')
'ab ab'
>>> re.sub('([\u0060-\u0065])', '\\1\\u0062', 'a a')
'a\\u0062 a\\u0062'
>>> re.sub('([\u0060-\u0065])', r'\1' '\u0062', 'a a')
'ab ab'

Добавить комментарий
Напишите свой ответ на данный вопрос.
Scroll Up