Форум сайта python.su
0
Привет, программисты на python.
У меня вопрос по регулярным выражениям. Я не могу понять, почему не работает моё выражение:
>>> re.search('^[а-яa-z]+$', 'ыве', re.L | re.M) >>>
Офлайн
221
а у меня работает
>>> print re.search('^[а-яa-z]+$', 'ыве', re.L | re.M).group() ыве
Офлайн
33
Какой версии питон?
Офлайн
20
Да вроде как и не должно работать. Почему бы не использовать `unicode` вместо `str`? Я полагаю, что движку `re` насрать на то как ты себе представляешь строку, utf8, cp866, как-то ещё, он обрабатывает строку побайтно, а не посимвольно. Если бы `re.search` в качестве ещё одного аргумента принимала кодировку, то можно было бы надеяться, а так без вариантов.
p.s. Речь о Python II, если что.
..bw
Отредактировано bw (Окт. 16, 2013 04:00:09)
Офлайн
8
bw
Ну да, на 2x нужно изобретать что-то типа
print re.search(u'^[а-яa-z]+$', u'ыве', re.L | re.M).group()
Офлайн
0
Спасибо за помощь. Python 2.7. А не расскажете, в двух словах, почему нужна такая магия?
P.S.
>>> print re.search('^[а-яa-z]+$', 'ыве', re.L | re.M).group()
Офлайн
20
Потому что u'' это строка `unicode`, это точно строка, а не набор байт, и каждый элемент представляет символ, а не половину как может быть в utf8. Для u'' уже не нужно указывать кодировку, кодировка только учитывается в момент компиляции. По возможности, лучше отдавать предпочтение `unicode`, в Python III вон вообще отменили обычные строки. `str` по сути это набор байт, как оно есть в Си и большинстве (если не во всех) других языков старше 10 лет. `unicode` внутрях интерпретатора представляется как ucs-2 или ucs-4.
..bw
Офлайн
0
Спасибо за ответ. Я примерно представляю различия строк и принцип их работы в python3.
Я не могу понять, и мне интересно, почему указанное выражение не работает в python2.7. Обе строки - и шаблон, и проверяемая, указаны в одной кодировке, к тому же, я думал, re.L должен помогать работать с не-unicode.
Офлайн
20
utf-8 не фиксированной же длинны. Как `re` поймёт что ему нужно то из одного, то из четырёх байт формировать символ. Очевидно никак, не предусмотрено, это естественный вывод из API так как кодировка нигде не передается в функциях. Вот что видит `re.search`:
>>> '^[а-яa-z]+$' '^[\xd0\xb0-\xd1\x8fa-z]+$' >>> len(_) 13 >>> 'ыве' '\xd1\x8b\xd0\xb2\xd0\xb5' >>> len(_) 6
Офлайн