Ошибка Python re.sub() для многострочной строки
У меня есть часть сценария, которая выглядит примерно так:
import re, sys
print(sys.version) # so you can see my Python version
repl = (
"use bravo\\api\\resources\\usersResource;\n"
"use bravo\\api\\resources\\groupsResource;\n"
"use bravo\\api\\resources\\bandsResource;\n"
"use bravo\\api\\resources\\setlistsResource;\n"
"use bravo\\api\\resources\\songsResource;"
)
pattern = r'\{\{\$use_table_resources\}\}'
string = "{{$use_table_resources}}"
re.sub(pattern, repl, string)
Всякий раз, когда я запускаю его, я получаю следующий вывод и ошибку:
3.6.2 |Anaconda, Inc.| (default, Sep 19 2017, 08:03:39) [MSC v.1900 64 bit (AMD64)]
Traceback (most recent call last):
File "test.py", line 15, in <module>
re.sub(pattern, repl, string)
File "C:\ProgramData\Anaconda3\lib\re.py", line 191, in sub
return _compile(pattern, flags).sub(repl, string, count)
File "C:\ProgramData\Anaconda3\lib\re.py", line 326, in _subx
template = _compile_repl(template, pattern)
File "C:\ProgramData\Anaconda3\lib\re.py", line 317, in _compile_repl
return sre_parse.parse_template(repl, pattern)
File "C:\ProgramData\Anaconda3\lib\sre_parse.py", line 904, in parse_template
raise s.error("missing <")
sre_constants.error: missing < at position 64 (line 2, column 26)
Это работает иногда, когда я делаю repl
замена строки короче, но я действительно не могу понять это. Насколько я могу сказать, я работаю в рамках их ограничений, в соответствии с API re.sub (...)
Я знаю, что этот простой случай не оправдывает использование регулярных выражений, но этот фрагмент кода взят из гораздо большей части программного обеспечения. Мне не нужны никакие ответы, говорящие мне, что регулярное выражение - неправильный подход, потому что это на самом деле самый простой случай, который я мог бы привести, который все еще воспроизводит проблему. Есть более сложные случаи, когда мне нужно, чтобы RegEx действительно выполнял свою работу.
В любом случае, я думаю, что проблема в содержимом замещающей строки, как ни странно, звучит. когда я использую более короткие строки замены, я не сталкиваюсь с этой ошибкой.
Любые указатели очень ценятся. Возможно, это что-то действительно крошечное и глупое, но я уже возвращался к этому несколько раз и не могу его найти.
1 ответ
В вашей замещающей строке недостаточно экранирования, поэтому обратный слеш интерпретируется механизмом регулярных выражений как начало захваченной группы (как в классическом r"\1"
или же "\\1"
без сырого префикса).
Вы можете добавить необработанный префикс перед каждой строкой, но я бы предпочел использовать многострочные необработанные строки, подобные этой (проще для чтения):
repl = r"""use bravo\\api\\resources\\usersResource;
use bravo\\api\\resources\\groupsResource;
use bravo\\api\\resources\\bandsResource;
use bravo\\api\\resources\\setlistsResource;
use bravo\\api\\resources\\songsResource;
"""
тогда полученная замена
use bravo\api\resources\usersResource;
use bravo\api\resources\groupsResource;
use bravo\api\resources\bandsResource;
use bravo\api\resources\setlistsResource;
use bravo\api\resources\songsResource;
Теперь без изменения ввода:
с помощью re.escape
лайк re.sub(pattern, re.escape(repl), string)
не работает так хорошо, потому что пробел и конец строки также экранированы
Но вы можете сделать это, поскольку знаете, что единственными проблемными символами являются обратные слеши:
re.sub(pattern, repl.replace("\\",r"\\"), string)
(он заменяет обратную косую черту двойной обратной косой чертой, и результат остается тем же)