питоннокривое 12.03.16 19:00 // оригинал
Чтобы набить руку, перетащил вспомогательные скрипты рабочего проекта с перла на питон. В процессе местами порадовался, местами исплевался. Некоторые вещи сперва привели в полное недоумение, окончательно с ними разобрался, пока писал этот поначалу еще более гневный пост, но даже после прояснения причины они оставили ощущение крайней неудовлетворенности и полной кривизны.
Ну ладно, я смирился с тем, что 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')), хоть возвращает она в точности ту же строку.
Полный демонстрационный код, закомментированы неработающие строчки: