#python #regex
Вопрос:
Я пытаюсь найти все экземпляры числа в уравнении. И для этого я написал этот скрипт на python:
re.findall(fr"([- */(]|^)({val})([- */)]|$)", equation)
Теперь, когда я даю ему это: 20 5-20
, и выполняю поиск 20
, результат будет таким, как ожидалось: [('', '20', ' '), ('-', '20', '')]
Но когда я просто делаю 20 20-5
это, это больше не работает , и я получаю только первый экземпляр: [('', '20', ' ')]
Я не понимаю, почему, это даже не проблема 20
быть в начале и в конце, например, это 5-20*4-20/3
все равно 20
будет очень хорошо сочетаться. Это просто не работает, когда значение повторяется последовательно
как мне это исправить?
Спасибо
Комментарии:
1. Что это
{val}
должно здесь означать?2. это форматирование строк python с использованием f-строк, просто игнорируйте его и думайте о {val} как о 20 в этом примере
Ответ №1:
Причина, по которой ваш шаблон изначально не работает 20 20-5
, заключается в том, что класс символов после сопоставления первого вхождения 20 фактически потребляет
После его использования для второго вхождения 20 сразу после него эта часть шаблона [- */(]|^)
не может совпадать, так как нет символа, соответствующего классу символов, и его нет в начале строки.
Используя 20, например, на месте {val}
, вы можете использовать поисковые запросы, которые не потребляют значение, а только утверждают, что оно присутствует.
Обратите внимание, что вам не нужно экранировать значения в классе символов, и для последнего утверждения вам не нужно добавлять другую группу, не связанную с захватом.
(?:(?<=[- */(])|^)20(?=[- */)]|$)
Демонстрация регулярных выражений
import re
strings = [
"20 5-20",
"20 20-5"
]
val = 20
pattern = fr"(?:(?<=[- */(])|^){val}(?=[- */)]|$)"
for equation in strings:
print(re.findall(pattern, equation))
Выход
['20', '20']
['20', '20']
Ответ №2:
Я предлагаю просто найти все числа (целое десятичное) в вашем выражении, а затем отфильтровать определенные значения:
inp = "20 5-20*3.20"
matches = re.findall(r'd (?:.d )?', inp)
matches = [x for x in matches if x == '20']
print(matches) # ['20', '20']
Каждое число в вашей формуле должно быть окружено только арифметическими символами, круглыми скобками или пробелами, все из которых не являются символами слов.
Комментарии:
1. это работает! но проблема в том, что я тоже допускаю нецелые числа (например, 3.20 не должно совпадать, но это происходит, если используется b). На этой ноте, как получилось, что ваша работает, а моя-нет, когда идея точно такая же?
2. @RRR В вашем текущем коде есть несколько синтаксических проблем. Учитывая ваши новые выявленные требования, я предлагаю просто найти все числа, а затем отфильтровать этот список для нужных вам значений.
Ответ №3:
Я думаю, что нашел ответ, но все еще не уверен, насколько он верен или почему он работает, а мой-нет :/
re.findall(fr"(?:(?<=[=- */(])|^)({val})(?:(?=[=- */)])|$)", equation
в основном, выполняется обратный и прямой поиск, чтобы узнать, находится ли значение между операциями