Прежде всего,
replacement patterns ≠ regular expression patterns
Мы используем шаблон регулярных выражений для поиска совпадений, мы используем шаблон замены для заменынайдено совпадений с регулярным выражением.
Синтаксис шаблона замены в Python
Документы re.sub
сбивают с толку, поскольку в них упоминаются обе escape-последовательности строк, которые могутиспользоваться в шаблонах замены (например, \n
, \r
) и escape-последовательностях регулярных выражений (\6
), а также в тех, которые могут использоваться как в качестве регулярных выражений, так и в escape-последовательностях строк (\&
).
IЯ использую термин regex escape-последовательность для обозначения escape-последовательности, состоящей из буквальной обратной косой черты + символа, то есть '\\X'
или r'\X'
и escape-последовательности строки дляОбозначим последовательность \
и символ или некоторую последовательность, которые вместе образуют действительную escape-последовательность строки .Они распознаются только в обычных строковых литералах .В необработанных строковых литералах вы можете экранировать только "
(и именно поэтому вы не можете завершить необработанный строковый литерал \"
, но обратная реакция по-прежнему является частью строки).
Таким образом, в шаблоне замены вы можете использовать обратные ссылки:
re.sub(r'\D(\d)\D', r'\1', 'a1b') # => 1
re.sub(r'\D(\d)\D', '\\1', 'a1b') # => 1
re.sub(r'\D(\d)\D', '\g<1>', 'a1b') # => 1
re.sub(r'\D(\d)\D', r'\g<1>', 'a1b') # => 1
Вы можете видеть, что r'\1'
и '\\1'
- это тот же шаблон замены, \1
.Если вы используете '\1'
, он получит синтаксический анализ как escape-последовательность строки , символ с восьмеричным значением 001
.Если вы забыли использовать префикс r
с однозначной обратной ссылкой, проблем не возникнет, поскольку \g
не является допустимой escape-последовательностью строки, и там в строке остается escape-символ \
.Прочитайте документы, на которые я ссылался:
В отличие от стандартного C, все нераспознанные escape-последовательности остаются в строке без изменений, т. Е. В результате остается обратный слеш.
Таким образом, когда вы передаете '\.'
в качестве строки замены, вы фактически отправляете комбинацию \.
с двумя символами в качестве строки замены, и поэтому вы получаете \.
в результате.
\
- это специальный символ в шаблоне замены Python
Если вы используете re.sub(r'\s+\.', r'\\.', text)
, вы получите тот же результат, что и в случаях text2
и text3
, см. thisdemo .
Это происходит потому, что \\
, две буквенные обратные косые черты, обозначают одну обратную косую черту в шаблоне замены.Если у вас нет группы 2 в шаблоне регулярных выражений, но в замене передано r'\2'
для замены на комбинацию символов \
и 2
, вы получите ошибку.
Таким образом, если у вас есть динамические определяемые пользователем шаблоны замещения, вам необходимо удвоить все обратные слеши в шаблонах замещения, которые должны передаваться в виде буквенных строк:
re.sub(some_regex, some_replacement.replace('\\', '\\\\'), input_string)