Python рекурсивное регулярное выражение для проверки соответствия круглых скобок? - PullRequest
0 голосов
/ 04 августа 2020

В настоящее время я работаю над анализатором математических функций в python, где я использую регулярное выражение для соответствия ожидаемым формам функций, например, 'f (x, y) = (x ^ 2, x + y)'

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

import re
import regex

def match_function(in_str):
    #Checks whether or not an input string matches the regular expression
    #for a function, in terms of what makes a function usually valid in mathematics

    #Returns an iterable of re.Match objects

    pattern = "([a-zA-Z]|[0-9])+\s*\({1}([a-zA-Z](,)*)+(\){1})\s*=+\s*(\()+[^()]*\){1}"

    return regex.finditer(regex, in_str) 

В этом решении регулярное выражение ожидает ровно одну открытую скобку и одну закрытую скобку. Я хотел бы обобщить это, чтобы принять любое количество (по крайней мере, одной) совпадающих открытых и закрытых круглых скобок.

Например, 'f (x, y, z) = (x * (y + z), y, z) '.

Просматривая онлайн-ресурсы, кажется, что библиотека python по умолчанию re для регулярного выражения не поддерживает рекурсию, поэтому я установил внешнюю библиотеку python regex (документация на https://pypi.org/project/regex/), который расширяет базовую функциональность библиотеки re.

Я попытался использовать выражение рекурсии (?R) в тестовой функции;

def match_closed_parentheses(in_str):
    pattern = "\((([^\(\)]*)|(?R))\)"
    return regex.match(pattern, in_str)

Я намерен провести этот тест функция для сопоставления любых строк формы: «((()) ())» с вложенными круглыми скобками.

Если скобки не совпадают, например, как в «(()))))» регулярное выражение должно match "(())".

Это также не заботит, если есть дополнительные открытые скобки: "((((()" должно соответствовать как "((((()", поскольку код внутри "основных" скобок будет анализироваться отдельно в компиляторе Dynami c.

Но вывод matched_closed_parentheses

print(match_closed_parentheses("()"))
print(match_closed_parentheses("(a,b,c)"))
print(match_closed_parentheses("(a+(b+c))"))

было не тем, что я ожидал:

<regex.Match object; span=(0, 2), match='()'>
<regex.Match object; span=(0, 7), match='(a,b,c)'>
None

Если бы кто-нибудь мог объяснить результат match_closed_parentheses и указать мне правильное направление, я был бы очень благодарен.

Изменить: разъяснена используемая мной внешняя библиотека регулярных выражений и предполагаемое поведение match_closed_parentheses

Изменить: я ценю полезные ответы, но я уже решил эту проблему. Проблема, с которой я столкнулся, заключалась в том, что я не проверял, повторялся ли узор внутри скобок ноль или более раз (Клини Стар). Я отмечу свой ответ как решенный через два дня, как только смогу.

Ответы [ 3 ]

0 голосов
/ 04 августа 2020
    def match_function(in_str):

    pattern = "[\w(\w,\w)]* = [(\w^\w, \w+\w)]*"

    result = re.search(pattern, in_str)
    if result:
        return result
    else:
        return "No match"
print(match_function('hello? world f(x,y) = (x^2, x+y)'))

вывод

<re.Match object; span=(13, 32), match='f(x,y) = (x^2, x+y)'>

Я не совсем понял, что вы хотите сделать, но, надеюсь, этот пример поможет. В противном случае, если вы используете python3, я настаиваю на import re, также ваше регулярное выражение неверно. Если вы новичок в Python регулярном выражении, я настоятельно рекомендую сначала пройти курс от базового c до промежуточного Python регулярного выражения. Иначе удачи.

0 голосов
/ 04 августа 2020

Вам придется разобраться с жесткими шаблонами регулярных выражений. Вот еще один пример соответствия 3 скобкам слева и справа. Я понял, что ваша настоящая проблема состоит в том, чтобы разработать точный шаблон, соответствующий вашим потребностям.

Я сделал для вас этот пример скобок, который будет соответствовать 1 скобке или более слева и справа с одним или несколькими \ w

 def match_function(in_str):

    pattern = "([(]*\w),(\w[)]*)"

    result = re.search(pattern, in_str)

    if result:
        return result
    else:
        return "No match"
print(match_function('hello? world f((((x,y))) = ((x^2, x+y))'))

вывод

<re.Match object; span=(14, 24), match='((((x,y)))'>
0 голосов
/ 04 августа 2020

Я разобрался в проблеме. Использование звездообразного оператора Клини во внутренней группе решает проблему:

pattern = "\((([^\(\)]*)|(?R))*\)"

Он даже отклоняет, когда есть слишком много открытых скобок, что желательно вместо того, чтобы оставлять их там, поэтому у динамического компилятора меньше проблем для устранения неполадок .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...