2013-05-30 17 views
16

ho i seguenti nomi di file che presentano questo modello:Python regex spaccatura senza stringa vuota

000014_L_20111007T084734-20111008T023142.txt 
000014_U_20111007T084734-20111008T023142.txt 
... 

Voglio estrarre mezzo due parti timestamp dopo la seconda sottolineatura '_' e prima '.txt'. Così ho usato la seguente espressione regolare Python stringa divisa:

time_info = re.split('^[0-9]+_[LU]_|-|\.txt$', f) 

Ma questo mi dà due stringhe vuote in più nella lista restituita:

time_info=['', '20111007T084734', '20111008T023142', ''] 

Come faccio ad avere solo le informazioni francobollo due volte? Io voglio:

risposta

12

Non utilizzare re.split(), utilizzare la metrica groups() od of regex Match/SRE_Match oggetti.

>>> f = '000014_L_20111007T084734-20111008T023142.txt' 
>>> time_info = re.search(r'[LU]_(\w+)-(\w+)\.', f).groups() 
>>> time_info 
('20111007T084734', '20111008T023142') 

È anche possibile assegnare un nome ai gruppi di cattura e recuperarli in un dizionario, anche se si utilizza groupdict() piuttosto che groups() per questo. (Il modello regex per un caso del genere sarebbe qualcosa come r'[LU]_(?P<groupA>\w+)-(?P<groupB>\w+)\.')

+0

Questa è una bella soluzione. Grazie. – tonga

+8

È un peccato che "split" non abbia l'opzione "nessuna stringa vuota". – Elazar

+1

@Elazar Non proprio, è solo questione di come 're.split()' sia implementato e quale sia lo scopo previsto. In casi come questo, ha più senso costruire un modello per i dati desiderati che crearne uno per abbinare tutto ciò che non è desiderato. (Anche se 'str.split()' in realtà rilascia stringhe vuote quando il separatore non è specificato o 'None'.) – JAB

13

Non sono un esperto di Python ma forse potresti semplicemente rimuovere le stringhe vuote dalla tua lista?

time_info = re.split('^[0-9]+_[LU]_|-|\.txt$', f) 
time_info = filter(None, str_list) 
+0

Questo funziona. Grazie. Mi chiedo se ci sia una soluzione one-pass usando la funzione 're.split()'. – tonga

+0

@tonga c'è, ma è meno carino: 'time_info = [x per x in re.split ('^ [0-9] + _ [LU] _ | - | \ .txt $', f) se x] ' – FraggaMuffin

+0

Poiché filter() restituisce un oggetto filtro, è necessario utilizzare list() in seguito:' time_info = list (filter (None, str_list)) ' –

2

Se i timestamp sono sempre dopo il secondo _ quindi è possibile utilizzare str.split e str.strip:

>>> strs = "000014_L_20111007T084734-20111008T023142.txt" 
>>> strs.strip(".txt").split("_",2)[-1].split("-") 
['20111007T084734', '20111008T023142'] 
+0

Mi piace fare queste cose senza RE. Non so perché. – Elazar

+0

@Ashwini: Grazie. Questo funziona. Ma come posso farlo con regex split? – tonga

+0

@Elazar Sospetto perché le espressioni regolari possono essere piuttosto criptici se sono fatte in modo sbagliato o sono troppo complesse e non hanno commenti. A volte una manipolazione di stringhe fatta con una RE può essere più facile da capire quando viene costruita come una serie di chiamate di funzione. (In questo caso, però, una serie di operazioni di accesso agli elementi 'split()'/'strip()'/element è più clandestina di quella che si avrebbe con una RE.) – JAB

1
>>> f='000014_L_20111007T084734-20111008T023142.txt' 
>>> f[10:-4].split('-') 
['0111007T084734', '20111008T023142'] 

o, un po 'più generale:

>>> f[f.rfind('_')+1:-4].split('-') 
['20111007T084734', '20111008T023142']