2012-04-15 20 views
6

Supponiamo che io sono una stringa come il seguente:un'espressione regolare per trovare il nome della funzione e tutti gli argomenti in Python

"func(arg1, arg2, arg3, arg4, ..., argn)" 

EDIT: Questa funzione non è in qualche particolare linguaggio. Ha solo questo formato. Se lo rende più facile, non pensarlo come una chiamata di funzione, solo una stringa.

Voglio scrivere un'espressione regolare per abbinare la funzione e ogni degli argomenti. Sto scrivendo questo in Python. L'uscita desiderata di questo è:

{"function" : "func", "arg" : ["arg1", "arg2", ... , "argn"]} 

EDIT: Mentre gli argomenti potrebbero essere chiamate di funzione, posso facilmente ricorsivamente provare a corrispondere con la stessa espressione regolare una volta Creo uno che funziona. Con questo intendo che posso ricorrere alla funzione con ciascuno degli argomenti. Ma questo non è veramente rilevante. Sono non cercando di creare un interprete, solo qualcosa per riconoscere gli argomenti.

Ecco il mio tentativo di questo:

import re 
s = "func(arg1, arg2, arg3, arg4, argn)" 
m = re.match(r"(?P<function>\w+)\s?\((?P<args>(?P<arg>\w+(,\s?)?)+)\)", s) 
print m.groupdict() 

Ed ecco l'output:

{'function': 'func', 'args': 'arg1, arg2, arg3, arg4, argn', 'arg': 'argn'} 

La funzione corrisponde bene, e così fa il set argomento. Tuttavia, non riesco a trovare una corrispondenza con gli argomenti individuali. Si tratta di un problema con la mia espressione regolare o una limitazione della corrispondenza delle espressioni regolari in Python?

EDIT2: Sono consapevole del fatto che ora posso dividere gli argomenti utilizzando il seguente codice:

d["arg"] = d["args"].split(", ") 

Ma mi chiedevo se avrei potuto fare tutto il lavoro con le espressioni regolari. In particolare, mi chiedo perché "arg" sia abbinato solo all'ultimo argomento.

EDIT3: Credo di essere (1) sperando di capire perché Python corrisponda solo all'ultimo argomento ogni volta, e (2) se posso fare lo schema modello in Python. O se c'è qualcosa di altrettanto intuitivo in Python come pattern matching in stile Scheme. Ho guardato il modulo ast e la sua sintassi è proibitivamente complessa.

+1

Questa chiamata di funzione è in una lingua particolare? Non dovresti usare un'espressione regolare per analizzare una lingua per la quale esiste già un parser corretto/completo ... – Borealid

+0

Non puoi farlo con le espressioni regolari (assumendo che tu voglia abbinare i singoli argomenti, che potrebbero essere chiamate di funzione). Hai bisogno di un parser vero e proprio. Se insisti a scrivere il tuo, allora leggi questo: http://effbot.org/zone/simple-iterator-parser.htm – Wes

+0

Potresti voler controllare [pyparsing] (http://pyparsing.wikispaces.com/) se stai pensando di fare qualcosa di più complesso. –

risposta

4

Sembra che tu sia il 90% lì, perché non basta scambiare i arg e args raggruppamenti e fare:

import re 

fn_match = re.match(r"(?P<function>\w+)\s?\((?P<arg>(?P<args>\w+(,\s?)?)+)\)", s) 
fn_dict = fn_match.groupdict() 
del fn_dict['args'] 
fn_dict['arg'] = [arg.strip() for arg in fn_dict['arg'].split(',')] 
+0

Sto cercando di catturare l'intera cosa come un'espressione regolare. Non è possibile? – BlackSheep

+0

Non per ottenere l'elenco risultante di argomenti che si desidera. Perché usare solo un coltellino svizzero quando hai un'intera cassetta degli attrezzi? – mVChr

7

Le espressioni regolari non possono analizzare linguaggi di programmazione complessi.

Se si sta solo cercando di analizzare Python, suggerisco di dare un'occhiata al modulo ast, che lo analizzerà per voi.

+0

Non sto provando ad analizzare Python, ma solo a catturare una sintassi molto specifica. Dal poco che ho letto, sembra che il modulo ast sia (1) specifico per Python e (2) sia piuttosto complesso per quello che sto cercando di fare. – BlackSheep

1

Per rispondere l'ultima parte della tua domanda: no Python non ha nulla simile a Schema "match", né ha pattern matching come ML/Haskell. La cosa più vicina che ha è la capacità di destrutturare cose come questa

>>> (a, [b, c, (d, e)]) = (1, [9, 4, (45, 8)]) 
>>> e 
8 

E per estrarre la testa e la coda di una lista (in Python 3.x) come questo ...

>>> head, *tail = [1,2,3,4,5] 
>>> tail 
[2, 3, 4, 5] 

ci sono alcuni moduli galleggianti intorno che fare modello reale corrispondenza in python, però, ma non posso garantire per la loro qualità.

Se ho dovuto farlo, vorrei implementare un po 'diverso - forse avere la capacità di inserimento di un tipo e opzionali argomenti (ad esempio la lunghezza, o il contenuto esatto) e una funzione da chiamare se corrisponde, così come match ([list, length = 3, check = (3, str), func]) che corrisponde (list _ _ somestr) e chiama func con somestr in scope, e potresti anche aggiungere altri pattern.

Problemi correlati