Почему регулярное выражение не работает?

Мне нужно заменить все вхождения нормальных пробелов в "статье 1", "статьях 2" и т. Д. Неразрывными пробелами. Конструкция ниже работает нормально:

 re.sub('(стат.{0,4}) (\d+)', r'\1 \2', text) # 'r' in repl is important, otherwise the word is not replaced correctly, at least for texts in Russian.

Однако я не хочу использовать повторно re.sub для "статья", затем для "пункт", затем для названий месяцев я хочу иметь словарь с выражениями регулярных выражений и заменами. Вот мой код, но он не работает должным образом: 'статья 1 статьи 2' должен выглядеть так 'статья(non-breaking space here)1 статьи(non-breaking space here)2':

 import re

 text = 'статья 1 статьи 2'
 dic = {'(cтат.{0,4}) (\d+)' : r'\1 \2'}


 def replace():
     global text
     final_text = ''
     for i in dic:
         new_text = re.sub(str(i), str(dic[i]), text)
         text = new_text
     return text

 print (replace())

1 ответ

Проблема в том, что вы скопировали и вставили неправильно.

Этот шаблон работает:

'(стат.{0,4}) (\d+)'

Этот не:

'(cтат.{0,4}) (\d+)'

Зачем? Потому что в первом и в поисковой строке первым символом является U+0441, маленькая кириллица Es. Но во втором это U+0063, латинская буква C. Конечно, они выглядят одинаково в большинстве шрифтов, но они не одинаковые символы.


Итак, как вы можете сказать? Ну, когда я заподозрил эту проблему, вот что я сделал:

>>> a = '(стат.{0,4}) (\d+)' # copied and pasted from your working code
>>> b = '(cтат.{0,4}) (\d+)' # copied and pasted from your broken code
>>> print(a.encode('unicode-escape').decode('ascii'))
(\u0441\u0442\u0430\u0442.{0,4}) (\\d+)
>>> print(b.encode('unicode-escape').decode('ascii'))
(c\u0442\u0430\u0442.{0,4}) (\\d+)

И разница очевидна: первый имеет \u0441 escape-последовательность, где второй имеет простой ASCII c,

Другие вопросы по тегам