Используя re в python3, я хочу сопоставить появление процентов в тексте и заменить их специальным токеном (например, заменить «30% -ное увеличение» на «A @ процент @ увеличение»).
Я хочу найти совпадение только в том случае, если процентное выражение является отдельным элементом. Например, он не должен соответствовать «Код продукта A322% n43%». Однако он должен совпадать, если строка содержит только одно процентное выражение, например «89%».
Я пробовал использовать разделители в своем регулярном выражении, например \ b, но поскольку% сам по себе не является буквенно-цифровым символом, он не улавливает конец выражения. Использование \ s делает невозможным уловить выражение, стоящее отдельно в строке.
На данный момент у меня есть код:
>>> re.sub(r"[+-]?[.,;]?(\d+[.,;']?)+%", ' @percent@ ', "1,211.21%")
' @percent '
который по-прежнему соответствует, если за выражением следуют буквы или другой текст (например, в примере кода продукта выше).
>>> re.sub(r"[+-]?[.,;]?(\d+[.,;']?)+%", ' @percent@ ', "EEE1,211.21%asd")
'EEE @percent@ asd'
Что ты посоветуешь?






Попробуйте поставить «первую» группу захвата на «вторую».
original: r"[+-]?[.,;]?(\d+[.,;']?)+%"
suggestd: r"[+-]?[.,;]?((\d+[.,;']?)+%)\b"
это не сработало, он все еще не определяет границу слова. Не работает, с "3%" в строке, само по себе, например
Похоже, идеальная работа для отрицательного просмотра назад и отрицательного просмотра вперед:
re.sub(r'''(?<![^\s]) [+-]?[.,;]? (\d+[.,;']?)+% (?![^\s.,;!?'"])''',
'@percent@', string, flags=re.VERBOSE)
(?<![^\s]) означает «отсутствие пробелов непосредственно перед текущей позицией разрешено» (при необходимости добавьте запрещенные символы).
(?![^\s.,;!?'"]) означает «запрещены пробелы, точки и т. д. Сразу после текущей позиции».
Демо: https://regex101.com/r/khV7MZ/1.
Отличный ответ. Предложение работает идеально, включает больше случаев, чем я считал (например, он отлично определяет 5% в «Вы сказали 5%?»), А инструмент, на который вы ссылаетесь, очень полезен! Спасибо.
игнорируются ли пробелы в вашем регулярном выражении? это потому, что они находятся между тройной кавычкой?
@AndresSuarez Пробелы игнорируются из-за flags=re.VERBOSE (но в [ ] пробелы не игнорируются). Тройные кавычки используются, чтобы избежать экранирования ' и ".
Примечание принято! Спасибо @Kirill
Попробуйте
re.sub(r'(?<!\w)-?\d[\d.,]*\b%\B', '@percent@', s).