Уведомления

Группа в Telegram: @pythonsu

#1 Май 27, 2021 14:51:18

Stright
От: Кострома
Зарегистрирован: 2015-01-20
Сообщения: 139
Репутация: +  16  -
Профиль   Отправить e-mail  

re.sub. Замена строкой, содержащей бекслеш

Пытаюсь заменить по шаблону. Строка, которой я хочу заменить шаблон, может содержать бекслеши, как один, так и несколько. Также вероятнее всего она может содержать и еще какие-то спецсимволы регулярных выражений.

 >>> 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'
?

Отредактировано Stright (Май 27, 2021 15:15:41)

Офлайн

#2 Май 27, 2021 15:26:33

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9843
Репутация: +  853  -
Профиль   Отправить e-mail  

re.sub. Замена строкой, содержащей бекслеш

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



Офлайн

#3 Май 27, 2021 15:30:50

Stright
От: Кострома
Зарегистрирован: 2015-01-20
Сообщения: 139
Репутация: +  16  -
Профиль   Отправить e-mail  

re.sub. Замена строкой, содержащей бекслеш

 >>> 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 (Май 27, 2021 15:33:18)

Офлайн

#4 Май 27, 2021 15:40:03

Stright
От: Кострома
Зарегистрирован: 2015-01-20
Сообщения: 139
Репутация: +  16  -
Профиль   Отправить e-mail  

re.sub. Замена строкой, содержащей бекслеш

И даже с сырой строкой получается ошибка в случае одного бекслеша:

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

Офлайн

#5 Май 27, 2021 16:12:30

Stright
От: Кострома
Зарегистрирован: 2015-01-20
Сообщения: 139
Репутация: +  16  -
Профиль   Отправить e-mail  

re.sub. Замена строкой, содержащей бекслеш

Сделал так:

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

Отредактировано Stright (Май 27, 2021 16:13:42)

Офлайн

#6 Май 27, 2021 22:01:42

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9843
Репутация: +  853  -
Профиль   Отправить e-mail  

re.sub. Замена строкой, содержащей бекслеш

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



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version