2012-01-26 15 views
5

Sto tentando di analizzare alcune docstring.regex: stringa con parti opzionali

un esempio docstrings è:

Test if a column field is larger than a given value 
    This function can also be called as an operator using the '>' syntax 

    Arguments: 
     - DbColumn self 
     - string or float value: the value to compare to 
      in case of string: lexicographic comparison 
      in case of float: numeric comparison 
    Returns: 
     DbWhere object 

Entrambe le parti Arguments e Returns sono opzionali. Voglio che la mia espressione regolare restituisca come gruppi la descrizione (prime righe), la parte Arguments (se presente) e la parte Returns (se presente).

L'espressione regolare che ho ora è:

m = re.search('(.*)(Arguments:.*)(Returns:.*)', s, re.DOTALL) 

e lavora nel caso in cui tutte e tre le parti sono presenti, ma non riesce più presto Arguments oi Returns parti non sono disponibili. Ho provato diverse varianti con i modificatori non golosi come ?? ma senza alcun risultato.

Edit: Quando le parti Arguments e Returns sono presenti, in realtà ho vorrebbe solo per corrispondere al testo dopo rispettivamente Arguments: e Returns:.

Grazie!

+1

L'ordine è sempre corretto? I. e., È 'Arguments' sempre dopo il testo standard e prima di' Returns'? –

+0

Sì, l'ordine è sempre corretto. – BioGeek

risposta

7

Prova con:

re.search('^(.*?)(Arguments:.*?)?(Returns:.*)?$', s, re.DOTALL) 

solo facendo il secondo e il terzo gruppo opzionale aggiungendo un ?, e rendendo le qualificazioni dei primi due gruppi non avido da (di nuovo) aggiungendo un ? su di loro (sì, confondendo).

Inoltre, se si utilizza il modificatore non avido nel primo gruppo del modello, corrisponderà alla sottostringa più breve possibile, che per .* è la stringa vuota. È possibile superare questo problema aggiungendo il carattere di fine riga ($) alla fine del modello, che costringe il primo gruppo ad abbinare il minor numero di caratteri possibile per soddisfare il modello, cioè l'intera stringa quando non c'è Arguments e no Sezioni Returns e tutto prima di quelle sezioni, quando presenti.

Edit: OK, se si desidera solo per catturare il testo dopo le Arguments: e Returns: gettoni, dovrete infilare in un altro paio di gruppi. Non abbiamo intenzione di utilizzare tutti i gruppi, in modo da dar loro un nome -con il <?P<name> notazione (un altro marchio domanda, argh!) - sta cominciando ad avere senso:

>>> m = re.search('^(?P<description>.*?)(Arguments:(?P<arguments>.*?))?(Returns:(?P<returns>.*))?$', s, re.DOTALL) 
>>> m.groupdict()['description'] 
"Test if a column field is larger than a given value\n This function can also be called as an operator using the '>' syntax\n\n " 
>>> m.groupdict()['arguments'] 
'\n  - DbColumn self\n  - string or float value: the value to compare to\n   in case of string: lexicographic comparison\n   in case of float: numeric comparison\n ' 
>>> m.groupdict()['returns'] 
'\n  DbWhere object' 
>>> 
+0

Funziona come un fascino! Come modificherai la regex se, per le parti opzionali, voglio solo abbinare il testo dopo 'Arguments' e' Returns'? – BioGeek

+0

Qualcosa come 're.search ('^ (. *?) (Argomenti: (. *?))? (Restituisce: (. *))? $', Doc, re.DOTALL)' funziona, ma non lo faccio ' t cura per il secondo e il quarto gruppo restituisce. – BioGeek

+0

Ho modificato la mia risposta. Basta nominare i gruppi e dimenticarsi di 'groups()', invece usare 'groupdict()'. – Chewie

3

Se si desidera far corrispondere la testo dopo le sezioni opzionali Arguments: e Returns:, E non si desidera utilizzare (?P<name>...) per denominare i gruppi di acquisizione, è inoltre possibile utilizzare, (?:...), la versione non di cattura di parentesi regolari.

La regex sarebbe simile a questa:

m = re.search('^(.*?)(?:Arguments:(.*?))?(?:Returns:(.*?))?$', doc, re.DOTALL) 
#      ^^     ^^ 

Secondo il python3 documentation:

(?:...)

Una versione non-cattura di parentesi regolari. Corrisponde a qualunque espressione regolare si trovi all'interno delle parentesi, ma la sottostringa corrispondente al gruppo non può essere recuperata dopo aver eseguito una corrispondenza o aver fatto riferimento in seguito nel modello.