Регулярные выражения Python для реализации неэкранирования строк
-
08-06-2019 - |
Вопрос
Я пытаюсь реализовать удаление строк с помощью регулярных выражений Python и обратных ссылок, и, похоже, это не очень хорошо работает.Я уверен, что это что-то, что я делаю неправильно, но я не могу понять, что именно...
>>> import re
>>> mystring = r"This is \n a test \r"
>>> p = re.compile( "\\\\(\\S)" )
>>> p.sub( "\\1", mystring )
'This is n a test r'
>>> p.sub( "\\\\\\1", mystring )
'This is \\n a test \\r'
>>> p.sub( "\\\\1", mystring )
'This is \\1 a test \\1'
Я бы хотел заменить \\[char] на \[char], но обратные ссылки в Python, похоже, не следуют тем же правилам, что и в любой другой реализации, которую я когда-либо использовал.Не мог бы кто-нибудь пролить немного света?
Решение
Разве не к этому приводит второй пример Андерса?
В 2.5 также есть string-escape
кодировка, которую вы можете применить:
>>> mystring = r"This is \n a test \r"
>>> mystring.decode('string-escape')
'This is \n a test \r'
>>> print mystring.decode('string-escape')
This is
a test
>>>
Другие советы
Ну, я думаю, вы, возможно, пропустили букву r или неправильно подсчитали обратную косую черту...
"\\n" == r"\n"
>>> import re
>>> mystring = r"This is \\n a test \\r"
>>> p = re.compile( r"[\\][\\](.)" )
>>> print p.sub( r"\\\1", mystring )
This is \n a test \r
>>>
Что, если я правильно понял, и было запрошено.
Я подозреваю, что более распространенный запрос заключается в следующем:
>>> d = {'n':'\n', 'r':'\r', 'f':'\f'}
>>> p = re.compile(r"[\\]([nrfv])")
>>> print p.sub(lambda mo: d[mo.group(1)], mystring)
This is \
a test \
>>>
Заинтересованный студент должен также прочитать книгу Кена Томпсона Размышления о доверии", где наш герой использует аналогичный пример, чтобы объяснить опасности доверия компиляторам, которые вы сами не загрузили из машинного кода.
Идея заключается в том, что я прочитаю экранированную строку и отменю ее экранирование (функция, которой явно не хватает в Python, для которой вам в первую очередь не нужно прибегать к регулярным выражениям).К сожалению, обратная косая черта меня не обманывает...
Еще один наглядный пример:
>>> mystring = r"This is \n ridiculous"
>>> print mystring
This is \n ridiculous
>>> p = re.compile( r"\\(\S)" )
>>> print p.sub( 'bloody', mystring )
This is bloody ridiculous
>>> print p.sub( r'\1', mystring )
This is n ridiculous
>>> print p.sub( r'\\1', mystring )
This is \1 ridiculous
>>> print p.sub( r'\\\1', mystring )
This is \n ridiculous
Что бы я хотел, чтобы это было напечатано, так это
This is
ridiculous
Вас обманывает представление результирующей строки в Python.Выражение Python:
'This is \\n a test \\r'
представляет собой строку
This is \n a test \r
думаю, именно этого ты и добивался.Попробуйте добавить 'print' перед каждым из ваших вызовов p.sub(), чтобы напечатать фактическую возвращаемую строку вместо представления строки в Python.
>>> mystring = r"This is \n a test \r"
>>> mystring
'This is \\n a test \\r'
>>> print mystring
This is \n a test \r
Отметка;его второй пример требует, чтобы каждый экранированный символ изначально помещался в массив, что генерирует KeyError, если экранирующей последовательности нет в массиве.Он умрет на чем угодно, кроме трех предоставленных символов (попробуйте \v), и перечислять все возможные escape-последовательности каждый раз, когда вы хотите отменить экранирование строки (или сохранить глобальный массив), является действительно плохим решением.Аналогично PHP, который использует preg_replace_callback()
с лямбдой вместо preg_replace()
, что совершенно не нужно в данной ситуации.
Извините, если я веду себя как придурок по этому поводу, я просто крайне разочарован Python.Это поддерживается любым другим движком регулярных выражений, который я когда-либо использовал, и я не могу понять, почему это не сработает.
Спасибо вам за ответ;тот самый string.decode('string-escape')
функция - это именно то, что я искал изначально.Если у кого-то есть общее решение проблемы обратной ссылки на регулярное выражение, не стесняйтесь опубликовать его, и я приму это как ответ.