BugTraq.Ru
Русский BugTraq
https://bugtraq.ru/lj/archive/2016/1203.1900.html

питоннокривое
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')), хоть возвращает она в точности ту же строку.

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

---------------------
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;

 
теги: программизм  |  обсудить  |  все отзывы (0)  |  обсудить в LJ [2064]
назад «  » вперед

аналогичные материалы
qtменюшное // 29.09.23 23:47
студийнораздутое // 08.03.17 02:24
плюсовое // 05.04.16 21:21
плюсношаблонное // 14.08.14 22:50
бустовское // 28.01.14 20:32
студийное // 28.10.13 20:00
ATLное // 07.04.13 19:08
стингрейное // 06.04.13 19:22
лентоньюшное // 21.01.13 19:27
дисковое // 10.11.12 22:21
 
последние записи
песчаное // 13.03.24 18:05
макоудаленное // 29.01.24 23:10
разнонедельное // 07.12.23 15:09
qtменюшное // 29.09.23 23:47
неестественноинтеллектуальное // 29.09.23 16:50
основательное // 18.09.23 00:15
отпускное // 06.08.23 00:26
вчерашнезавтрашнее // 02.07.23 15:25
позитивное // 27.06.23 13:05
тейлскейлное // 18.04.23 20:43





  Copyright © 2001-2024 Dmitry Leonov Design: Vadim Derkach