2016-02-28 15 views
7
In [29]: re.findall("([abc])+","abc") 
Out[29]: ['c'] 

In [30]: re.findall("[abc]+","abc") 
Out[30]: ['abc'] 

Confuso da quello raggruppato. Come fa la differenza?differenza tra due espressioni regolari: [abc] + e ([abc]) +

+0

're.findall' lancia una chiave nell'analisi poiché' re.findall ("[abc] +", "abc") 'cattura comunque senza la parentesi (mostra la corrispondenza completa quindi ...) Prova' re .search (r '([abc]) +', 'abc'). group (1) 'e' re.search (r '([abc] +)', 'abc'). group (1) ' – dawg

risposta

8

Ci sono due cose che devono essere spiegate qui: il comportamento dei gruppi quantificati e la progettazione del metodo findall().

Nel tuo primo esempio, [abc] corrisponde allo a, che viene catturato nel gruppo # 1. Quindi corrisponde allo b e lo cattura nel gruppo # 1, sovrascrivendo lo a.Poi di nuovo con il c, e questo è ciò che è rimasto nel gruppo # 1 alla fine della partita.

Ma è corrisponde a corrisponde all'intera stringa. Se si stesse utilizzando search() o finditer(), si sarebbe in grado di guardare MatchObject e vedere che group(0) contiene abc e group(1) contiene c. Ma findall() restituisce stringhe, non MatchObjects. Se non ci sono gruppi, restituisce una lista delle partite complessive; se ci sono gruppi, l'elenco contiene tutte le acquisizioni, ma non la partita complessiva.

Quindi entrambe le espressioni regolari corrispondono all'intera stringa, ma la prima cattura e scartando singolarmente ogni carattere (che è un po 'inutile). È solo il comportamento imprevisto di findall() che fa sembrare che stai ottenendo risultati diversi.

-3

Il raggruppamento ha solo una diversa preferenza.

([abc])+ => Trova uno dalla selezione. Può abbinare uno o più. Trova una e tutte le condizioni sono soddisfatte in quanto + significa 1 o più. Questo rompe la regex in due fasi.

Mentre il gruppo non raggruppato viene considerato nel suo complesso.

+3

Questa spiegazione è completamente sbagliata. Non c'è nessun cortocircuito coinvolto. Se questa spiegazione fosse corretta, il primo 'findall' avrebbe restituito' ['a'] 'invece di' ['c'] '. – user2357112

+0

I cortocircuiti potrebbero essere il termine sbagliato. tutte le condizioni sono soddisfatte. - cambia lingua per riflettere –

+2

No, non è solo "cortocircuito" essere il termine sbagliato. Il meccanismo al lavoro non funziona nel modo in cui descrivi. Come un altro esempio, '^ ([abc]) + $' non dà ''abc'' neanche; [dà ancora '['c']'] (http://ideone.com/Mj9Wh2). – user2357112

0

input "abc"

[abc] 

partita un singolo carattere => "a"

[abc]+ 

+ Tra uno e periodi illimitati, tante volte quanto possibile => "abc"

([abc]) 

gruppo di cattura ([abc]) => "a"

([abc])+ 

+ Un ripetuto gruppo cattura catturerà solo l'ultima iterazione => "c"

7

Nel primo esempio si dispone di un gruppo di catturato ripetuto che cattura solo l'ultima iterazione. Qui c.

([abc])+ 

Regular expression visualization

Debuggex Demo

Nel secondo esempio si sta corrispondono a un singolo carattere nella lista una volta e illimitate.

[abc]+ 

Regular expression visualization

Debuggex Demo

2

Ecco il modo in cui vorrei pensarci. ([abc])+ sta tentando di ripetere un gruppo catturato. Quando si usa "+" dopo il gruppo di cattura, non significa che si otterranno due gruppi catturati. Quello che succede, almeno per la regex di Python e la maggior parte delle implementazioni, è che il "+" forza l'iterazione finché il gruppo di cattura non contiene solo l'ultima corrispondenza.

Se si desidera acquisire un'espressione ripetuta, è necessario invertire l'ordine di "(...)" e "+", ad es. invece di ([abc])+ utilizzare ([abc]+).

Problemi correlati