0
0 Комментариев

Поясню сразу: я знаю, что python 2 требует явного объявления строк как юникодовых. Понимаю, что это и не должно работать корректно. Мне интересна «анатомия» поломки. Что именно внутри re.compile() и regex.search() производит такой результат?


Судя по нижеприведённому коду, диапазон 'а-яё' не включает в себя диапазон 'р-ю', зато диапазон 'р-ю' включает 'ё'.

mcve.py:

# coding=utf-8
 
import re
 
# Это панграмма, она содержит все буквы алфавита
test = 'широкая электрификация южных губерний даст мощный толчок подъёму сельского хозяйства'
 
regex1 = re.compile('[а-яА-ЯёЁ\s]+')
regex2 = re.compile('[а-яА-ЯёЁшьрэтфцюыхущчъ\s]+')
regex3 = re.compile('[а-яёшьрэтфцюыхущчъс\s]+')
regex4 = re.compile('[а-яр-ю\s]+')
 
print regex1.search(test).group()
print regex2.search(test).group()
print regex3.search(test).group()
print regex4.search(test).group()

Результат:


широкая электрификация южных губерний даст мощный толчок подъёму сельского хозяйства
широкая электрификация южных губерний даст мощный толчок подъёму сельского хозяйства
широкая электрификация южных губерний даст мощный толчок подъёму сельского хозяйства

Я убедился, что все буквы алфавита от «А» до «Я» и от «а» до «я» идут в Юникоде подряд, кроме «Ёё», которые явным образом добавлены в регулярное выражение.

Постепенно добавляя буквы, на которых прерывается поиск по первому выражению, я пришёл к диапазону а-яА-ЯёЁшьрэтфцюыхущчъ. Если отсортировать добавленные буквы, получается почти сплошной интервал: "ртуфхцчшщъыьэю".

Если убрать заглавные буквы, т.е. "[А-ЯЁ]", то неожиданным образом поиск прерывается на «с». Интервал становится сплошным: с «р» и до «ю». Это regex3.

И наконец оказывается, что теперь интервал можно свернуть и даже убрать «ё» (regex4).

Что вообще происходит?

 python --version
Python 2.7.6


Если явным образом сделать юникодовую строку и регулярное выражение, то всё работает как должно. Но ведь как-то работает и без этого. Объясните, как?

test2 = u'широкая электрификация южных губерний даст мощный толчок подъёму сельского хозяйства'
regex5 = re.compile(u'[а-яА-ЯёЁ\s]+')


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