2011-02-10 11 views
23

Mi sto confondendo restituendo più gruppi in Python. Il mio RegEx è questo:Python RegEx multiple groups

lun_q = 'Lun:\s*(\d+\s?)*' 

E la mia stringa è

s = '''Lun:      0 1 2 3 295 296 297 298'''` 

torno un oggetto abbinato, e poi voglio guardare i gruppi, ma tutti si vede che l'ultimo numero (258):

r.groups() 
(u'298',) 

Perché non restituisce gruppi di 0,1,2,3,4 ecc.?

+3

Penso che quello che si fa riferimento direttamente a si chiama [Cattura di un gruppo ripetuto] (http://www.regular-expressions.info/captureall .html) - o lungo le linee 'accesso a ogni partita in un gruppo di cattura quantificato/ripetuto'. vedi [questa risposta simile] (http://stackoverflow.com/a/3537914/611007) per javascript. non lo so per certo ma *** sembra che non siano supportati dal gusto regex di python ***. vedi [richiesta di miglioramento python correlata] (http://bugs.python.org/issue7132) e [domanda correlata] (http://stackoverflow.com/q/15908085/611007) – n611x007

risposta

20

L'espressione regolare contiene solo una coppia di parentesi (un gruppo di acquisizione), in modo da ottenere un solo gruppo nella corrispondenza. Se si utilizza un operatore di ripetizione su un gruppo di acquisizione (+ o *), il gruppo viene "sovrascritto" ogni volta che si ripete il gruppo, ovvero viene catturata solo l'ultima corrispondenza.

Nel tuo esempio qui, probabilmente stai meglio usare .split(), in combinazione con una regex:

lun_q = 'Lun:\s*(\d+(?:\s+\d+)*)' 
s = '''Lun: 0 1 2 3 295 296 297 298''' 

r = re.search(lun_q, s) 

if r: 
    luns = r.group(1).split() 

    # optionally, also convert luns from strings to integers 
    luns = [int(lun) for lun in luns] 
+3

Picking 're.match()' vs 're.split()' è una decisione non banale – smci

2

Un altro approccio sarebbe quello di utilizzare l'espressione regolare si deve convalidare i dati e quindi utilizzare un altro regex specifico che targetizza ogni elemento che desideri estrarre utilizzando un iteratore di corrispondenza.

import re 
s = '''Lun: 0 1 2 3 295 296 297 298''' 
lun_validate_regex = re.compile(r'Lun:\s*((\d+)(\s\d+)*)') 
match = lun_validate_regex.match(s) 
if match: 
    token_regex = re.compile(r"\d{1,3}") 
    match_iterator = token_regex.finditer(match.group(1)) 
    for token_match in match_iterator: 
     #do something brilliant 
+0

print re.findall ('\ d', s) –

6

A volte è più semplice senza regex.

>>> s = '''Lun: 0 1 2 3 295 296 297 298''' 
>>> if "Lun: " in s: 
...  items = s.replace("Lun: ","").split() 
...  for n in items: 
...  if n.isdigit(): 
...   print n 
... 
0 
1 
2 
3 
295 
296 
297 
298 
1

Se siete alla ricerca di un uscita come ad esempio 0,1,2,3,4 ecc La simples risposta è al di sotto.

stampa re.findall ('\ d', s)