Найти - Пользователи
Полная версия: re.sub. Замена строкой, содержащей бекслеш
Начало » Python для экспертов » re.sub. Замена строкой, содержащей бекслеш
1
Stright
Пытаюсь заменить по шаблону. Строка, которой я хочу заменить шаблон, может содержать бекслеши, как один, так и несколько. Также вероятнее всего она может содержать и еще какие-то спецсимволы регулярных выражений.
 >>> import re
>>> category_name = 'SWITCH\\ELECTRONIC DEVICE'
>>> re.sub('{{ category_name }}', category_name, 'Category name: {{ category_name }}')
Traceback (most recent call last):
  File "/home/stright/.pyenv/versions/3.9.5/lib/python3.9/sre_parse.py", line 1039, in parse_template
    this = chr(ESCAPES[this][1])
KeyError: '\\E'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/home/stright/.pyenv/versions/some_interpreter/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3441, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-4-b3dbd0a62f2d>", line 1, in <module>
    re.sub('{{ category_name }}', category_name, 'Category name: {{ category_name }}')
  File "/home/stright/.pyenv/versions/3.9.5/lib/python3.9/re.py", line 210, in sub
    return _compile(pattern, flags).sub(repl, string, count)
  File "/home/stright/.pyenv/versions/3.9.5/lib/python3.9/re.py", line 327, in _subx
    template = _compile_repl(template, pattern)
  File "/home/stright/.pyenv/versions/3.9.5/lib/python3.9/re.py", line 318, in _compile_repl
    return sre_parse.parse_template(repl, pattern)
  File "/home/stright/.pyenv/versions/3.9.5/lib/python3.9/sre_parse.py", line 1042, in parse_template
    raise s.error('bad escape %s' % this, len(this))
re.error: bad escape \E at position 6
Пробовал применить к строке-замене re.escape, но происходит экранирование пробелов:
 >>> re.sub('{{ category_name }}', re.escape(category_name), 'Category name: {{ category_name }}')
>>> 'Category name: SWITCH\\ELECTRONIC\\ DEVICE'
Также, если строка-замена содержит один бекслеш, то в результате получается двойной слеш:
 >>> category_name = 'SWITCH\ELECTRONIC DEVICE'
>>> re.sub('{{ category_name }}', re.escape(category_name), 'Category name: {{ category_name }}')
>>>  'Category name: SWITCH\\ELECTRONIC\\ DEVICE'
С точками в строке:
 >>> category_name = 'SWITCH.ELECTRONIC\ DEVICE'
>>> re.sub('{{ category_name }}', re.escape(category_name), 'Category name: {{ category_name }}')
>>> 'Category name: SWITCH\\.ELECTRONIC\\\\ DEVICE'
Есть ли какой-нибудь способ сделать замену шаблона без искажения, чтобы в результате получилась строка:
'Category name: SWITCH\\ELECTRONIC DEVICE'
?
py.user.next
  
>>> import re
>>> 
>>> category_name = r'SWITCH\\ELECTRONIC DEVICE'
>>> re.sub(re.escape('{{ category_name }}'), category_name, 'Category name: {{ category_name }}')
'Category name: SWITCH\\ELECTRONIC DEVICE'
>>>
Stright
 >>> category_name = 'SWITCH ELECTRONIC\ DEVICE'
>>> re.sub(re.escape('{{ category_name }}'), category_name, 'Category name: {{ category_name }}')
>>> 'Category name: SWITCH ELECTRONIC\\ DEVICE'
Появляется дубль бекслеша в результате. И category_name у меня не сырая строка
Stright
И даже с сырой строкой получается ошибка в случае одного бекслеша:
 >>> category_name = r'SWITCH \ELECTRONIC DEVICE'
>>> re.sub(re.escape('{{ category_name }}'), category_name, 'Category name: {{ category_name }}')
Traceback (most recent call last):
  File "/home/stright/.pyenv/versions/3.9.5/lib/python3.9/sre_parse.py", line 1039, in parse_template
    this = chr(ESCAPES[this][1])
KeyError: '\\E'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/home/stright/.pyenv/versions/some_interpreter/lib/python3.9/site-packages/IPython/core/interactiveshell.py", line 3441, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-34-2f77c357ec22>", line 1, in <module>
    re.sub(re.escape('{{ category_name }}'), category_name, 'Category name: {{ category_name }}')
  File "/home/stright/.pyenv/versions/3.9.5/lib/python3.9/re.py", line 210, in sub
    return _compile(pattern, flags).sub(repl, string, count)
  File "/home/stright/.pyenv/versions/3.9.5/lib/python3.9/re.py", line 327, in _subx
    template = _compile_repl(template, pattern)
  File "/home/stright/.pyenv/versions/3.9.5/lib/python3.9/re.py", line 318, in _compile_repl
    return sre_parse.parse_template(repl, pattern)
  File "/home/stright/.pyenv/versions/3.9.5/lib/python3.9/sre_parse.py", line 1042, in parse_template
    raise s.error('bad escape %s' % this, len(this))
re.error: bad escape \E at position 7
Stright
Сделал так:
 >>> import re
>>> pattern = re.compile(r'{{ category_name }}')
>>> category_name = 'SWITCH\\ELECTRONIC DEVICE'
>>> s = 'Category name: {{ category_name }} {{ category_name }} some text'
>>> while m := pattern.search(s):
>>>     start_pos, end_pos = m.span()
>>>     s = f'{s[:start_pos]}{category_name}{s[end_pos:]}'
>>> s
>>> 'Category name: SWITCH\\ELECTRONIC DEVICE SWITCH\\ELECTRONIC DEVICE some text'
py.user.next
Stright
И даже с сырой строкой получается ошибка в случае одного бекслеша
  
>>> import re
>>> 
>>> category_name = r'SWITCH \\ELECTRONIC DEVICE'
>>> re.sub(re.escape('{{ category_name }}'), category_name, 'Category name: {{ category_name }}')
'Category name: SWITCH \\ELECTRONIC DEVICE'
>>> print(_)
Category name: SWITCH \ELECTRONIC DEVICE
>>>
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB