python: использование позитивного просмотра назад и позитивного просмотра вперед
Необходимо в python в выражениях найти блоки +-/(цифры#!)+-/ (ну или от начала или от конца строки) и удалить () оставив начинку внутри
делаю так:
использую регулярное выражение
(?<=[-+*%\/]|^)(\(([0-9!#]+)\))(?=[-+*%\/]|$)
в коде
print(re.sub(r'(?<=[-+*%\/]|^)(\(([0-9!#]+)\))(?=[-+*%\/]|$)', r'\2', txt))
и получаю ошибку
raise error("look-behind requires fixed-width pattern")
re.error: look-behind requires fixed-width pattern
что не так с шаблоном и как его использовать корректно для данной задачи или как его переделать?
условно чтобы
(12!)*(7!)+9
превратилось в
12!*7!+9
Ответы (1 шт):
Эта проблема и её решения описаны мной на английском StackOverflow здесь.
Модуль регулярных выражений PyPi, устанавливаемый с помощью pip install regex (или pip3 install regex), решает данную проблему целиком и полностью, так как поддерживает шаблоны любой длины в блоке предварительного просмотра назад.
В регулярных выражениях библиотеки re шаблон предварительного просмотра назад действительно должен иметь фиксированную длину. Когда внутри него есть чередования различной длины, есть несколько решений этой проблемы.
- Перепишите шаблон так, чтобы вам не приходилось использовать чередование. Если шаблон в просмотре назад представляет собой чередование "якоря" с одним символом (как в текущем вопросе), вы можете изменить знак просмотра назад и использовать отрицательный класс символов с символом внутри. Например,
(?<=\s|^)\w+(?=\s|$)обычно можно записать с помощью двойного отрицания как(?<!\S)\w+(?!\S).(?<=\s|^)находит либо пробел, либо начало строки. В библиотекеreвместо него используйте(?<!\S).(?<=^|;)можно преобразовать в(?<![^;])(при тестировании на онлайн-сайтах добавьте\nк классу отрицательных символов, например(?<![^;\n]) - Разделите чередования внутри блока предварительного просмотра на отдельные блоки предварительного просмотра:
- Позитивные просмотры назад необходимо чередовать в группе (например,
(?<=a|bc)следует переписать как(?:(?<=a)|(?<=bc))) - Отрицательные результаты просмотра можно поместить один за другим (например,
(?<!^|,)"(?!,|$)должен выглядеть как(?<!^)(?<!,)"(?!,|$)).
- Позитивные просмотры назад необходимо чередовать в группе (например,
Ответ
Вы можете использовать
(?<![^-+*%/])(\(([0-9!#]+)\))(?![^-+*%/])
См. пример работы выражения (в тесте добавлен знак переноса строки, который будет полезен при тестировании сразу нескольких строк).