Можете ли вы использовать одно регулярное выражение для анализа параметров функции? - PullRequest
2 голосов
/ 08 октября 2010

Задача

В какой-то момент файла существует программный файл, содержащий следующий фрагмент кода.

...

food($apples$ , $oranges$ , $pears$ , $tomato$){
  ...
}

...

Эта функция может содержать любое количество параметров, но они должны быть строками, разделенными запятыми. Все строки параметров являются строчными словами.

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

["apples", "oranges", "pears", "tomato"]

Попытка решения

Используя модуль python RE, я смог добиться этого, разбив проблему на две части.

  1. Найдите функцию в коде и извлеките список параметров.

    plist = re.search(r'food\((.*)\)', programString).group(1)
    
  2. Разделить список, используя другое регулярное выражение.

    params = re.findall(r'[a-z]+', plist)
    

Вопрос

Можно ли как-нибудь достичь этого с помощью одного регулярного выражения вместо двух?

Редактировать

Благодаря ответу Тима Пицкера мне удалось найти несколько связанных вопросов:

  1. Регулярные выражения Python - как получить несколько групп из группового выражения?
  2. Какие регулярные выражения поддерживают захваты (в отличие от групп захвата)?

Ответы [ 5 ]

2 голосов
/ 08 октября 2010

Чтобы ответить на ваш вопрос «Можно ли сделать это в одном регулярном выражении?»: Да, но не в Python.

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

Так что в Python вам нужно сделать это в два шага (find весь вызов функции food(...), а затем findall отдельных совпадений со вторым регулярным выражением, как предложено Динго).

Или используйте синтаксический анализатор наподобие pyparsing Пола Макгуайра.

2 голосов
/ 08 октября 2010

Pyparsing удобен для такого рода вещей, когда вы не знаете, когда натолкнетесь на лишние пробелы, комментарии, что угодно.Подобно именованным группам в RE, этот пример определяет имя результатов 'параметры', которое используется для извлечения нужных данных:

>>> code = """\
... ...
...
... food($apples$ , $oranges$ , $pears$ , $tomato$){
...   ...
... }
... ...
... food($peanuts$, $popcorn$ ,$candybars$ ,$icecream$){
...   ...
... }
... """
>>> from pyparsing import *
>>> LPAR,RPAR,LBRACE,RBRACE,DOLLAR = map(Suppress,"(){}$")
>>> param = DOLLAR + Word(alphas) + DOLLAR
>>> funcCall = "food" + LPAR + delimitedList(param)("parameters") + RPAR + LBRACE
>>> for fn in funcCall.searchString(code):
...   print fn.parameters
...
['apples', 'oranges', 'pears', 'tomato']
['peanuts', 'popcorn', 'candybars', 'icecream']

Если я изменю вторую функцию на:

... food($peanuts$, $popcorn$ ,/*$candybars$ ,*/$icecream$){

И затем добавьте эту строку:

>>> funcCall.ignore(cStyleComment)

Тогда я получу:

>>> for fn in funcCall.searchString(code):
...   print fn.parameters
...
['apples', 'oranges', 'pears', 'tomato']
['peanuts', 'popcorn', 'icecream']
1 голос
/ 08 октября 2010

Почему регулярное выражение?

for line in open("file"):
    line=line.rstrip()
    if line.lstrip().startswith("food") :
        for item in line.split(")"):
            if "food" in item:
                print item.split("(")[-1].split(",")

выход

$ ./python.py
['$apples$ ', ' $oranges$ ', ' $pears$ ', ' $tomato$']
0 голосов
/ 08 октября 2010

Что-то вроде этого регулярного выражения должно работать

food\((\$(?<parm>\w+)\$\s*,?\s*)+\).*

помещает все совпадающие имена параметров в группу 'parm'

0 голосов
/ 08 октября 2010
params = re.findall(r'\$([a-z]+)\$', programString)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...