Dmitry Leonov (leonov) wrote,
Dmitry Leonov
leonov

питоннокривое

Чтобы набить руку, перетащил вспомогательные скрипты рабочего проекта с перла на питон. В процессе местами порадовался, местами исплевался. Некоторые вещи сперва привели в полное недоумение, окончательно с ними разобрался, пока писал этот поначалу еще более гневный пост, но даже после прояснения причины они оставили ощущение крайней неудовлетворенности и полной кривизны.

Ну ладно, я смирился с тем, что raw strings не помогают в случае последнего '\' в строке (да, действительно, в такой строке может встретиться внутренний ', который нужно эскейпить, и различить две ситуации с \' невозможно). Смирился и с тем, что в подобной ситуации в случае регекспа один заменяемый слеш приходится изображать четырьмя. Но полной неожиданностью стало то, что та же фигня творится и со строкой замены, т.е. со вторым параметром sub.

Т.е. вполне ожидаемо, что print (re.sub('a', '\n', 'a a a')) превратит три "а" в три перевода строки. Менее очевидно, но то же самое происходит при print (re.sub('a', r'\n', 'a a a')). По той же логике print (re.sub('a', '\\', 'a a a')) выдает ошибку и приходится использовать print (re.sub('a', '\\\\', 'a a a')). Похоже, что это сделали ради обработки всяких \1, из-за которых и строку замены стали обрабатывать аналогично шаблонной, другого объяснения я найти не могу.

Что гораздо более неприятно, та же ерунда происходит, если эти слеши пришли в переменной, которая может использоваться и в других местах, где лишний слеш совсем ни к чему (какая-нибудь path = r'path\to\file', которая той же print выводится as is). И это уже заметно ломает поведение при переносе кода с перла - получается, что перед отправкой в регексп такую переменную нужно дополнительно обрабатывать. Причем re.escape тут, к сожалению, не помогает, поскольку портит другие символы. Небольшим утешением стало то, что подсовывание функции/лямбды ситуацию вроде бы лечит: print (re.sub('a', lambda m: '\\', 'a a a')), хоть возвращает она в точности ту же строку.

Полный демонстрационный код, закомментированы неработающие строчки:

---------------------
import re

a = 'a a a'
sl = '\\'
n = r'\n'

print (sl, n)

print (1, re.sub('a', r'\n', a))
print (2, re.sub('a', '\n', a))
print (3, re.sub('a', n, a))
print (4, re.sub('a', lambda m: r'\n', a))
print (5, re.sub('a', lambda m: n, a))

print (6, re.sub('a', '\\\\', a))
print (7, re.sub('a', lambda m: '\\', a))
print (8, re.sub('a', lambda m: sl, a))

# print (re.sub('a', '\\', a))
# print (re.sub('a', sl, a))
---------------------
Аналогичный код на перле выдает вполне предсказуемый результат:
$a = 'a a a';
$n = '\n';
$a =~ s/a/$n/g;
print $a;
Tags: программизм
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

  • 2 comments