2013-05-19 21 views
6

Ho una regex .net che sto testando con Windows PowerShell. L'uscita è il seguente:Quantificatore di regex non-goloso dà un risultato goloso

> [System.Text.RegularExpressions.Regex]::Match("aaa aaa bbb", "aaa.*?bbb") 


Groups : {aaa aaa bbb} 
Success : True 
Captures : {aaa aaa bbb} 
Index : 0 
Length : 11 
Value : aaa aaa bbb 

mia aspettativa era che usando l'? quantificatore causerebbe la partita per essere aaa bbb, come il secondo gruppo di uno della partita è sufficiente a soddisfare l'espressione. La mia comprensione dei quantificatori non avidi è difettosa, o sto verificando in modo errato?

Nota: questo non è chiaramente lo stesso problema Regular Expression nongreedy is greedy

risposta

5

Questo è un malinteso comune. I quantificatori pigri non garantiscono la corrispondenza più breve possibile. Si accertano solo che il quantificatore corrente, dalla posizione corrente, non corrisponda a più caratteri del necessario per una corrispondenza complessiva.

Se si vuole veramente garantire la corrispondenza più breve possibile, è necessario renderlo esplicito. In questo caso, ciò significa che al posto di .*?, si desidera una sottostringa che corrisponda a qualsiasi cosa che non sia né aaabbb. L'espressione regolare risultante sarà dunque

aaa(?:(?!aaa|bbb).)*bbb 
+0

Ho appena fatto ciò che avrei dovuto fare in primo luogo e ho consultato il capitolo pertinente di Friedl. Questo mi ha portato a 'aaa ((?! Aaa).) * Bbb', che è più o meno quello che hai detto, tranne che la tua risposta ha i dettagli aggiunti di rendere la sottoespressione non catturante e anche i test per bbb in negativo guarda avanti. Bella risposta. –

5

Confrontare il risultato per la stringa aaa aaa bbb bbb:

regex: aaa.*?bbb 
result: aaa aaa bbb 

regex: aaa.*bbb 
result: aaa aaa bbb bbb 

Il motore regex trova prima occorrenza di aaa e poi salta tutte caratteri (.*?) fino a prima occorrenza di bbb, ma per l'operatore goloso (.*) si andrà avanti per trovare un risultato più grande e pertanto corrisponde alle las t Occorrenza di bbb.

+0

Questa è la spiegazione più chiara di quello che sta succedendo. +1 – duozmo

0

Beh, è ​​molto semplice, abbiamo la seguente stringa

aaa aaa bbb

Vediamo abbiamo questa regex aaa.*?bbb. Il motore regex inizierà con aaa

aaa aaa bbb

Il motore regex ha ora .*?bbb. Si procederà con la space

aaa spazio aaa bbb

ma abbiamo ancora alcuni personaggi fino bbb? Così il motore regex continuerà la sua strada e abbinare il secondo set di un

aaa spazio aaa bbb

Infine il motore regex corrisponderà bbb:

aaa aaa bbb


Quindi vediamo, se vogliamo solo per abbinare il secondo aaa potremmo usare la seguente espressione regolare:

(?<!^)aaa.*?bbb, questo significa per abbinare aaa che non è all'inizio della frase.

Possiamo anche utilizzare aaa(?= bbb).*?bbb, questo significa corrispondere a aaa seguito da space bbb.

vederlo lavorare 1 - 2.

Sono appena tornato in me, ma perché non usi direttamente lo aaa bbb?

1

Questo non è un problema avido/pigro. Il problema deriva dal fatto che la stringa viene analizzata da sinistra a destra. Quando viene abbinato il primo aaa, il motore regex aggiunge i caratteri uno alla volta per ottenere il modello completo.

Nota che con un comportamento avido, nel tuo esempio, ottieni lo stesso risultato: il primo aaa è abbinato, il motore regex prende tutti gli ultimi caratteri e torna indietro carattere per carattere fino ad avere la corrispondenza completa.

Problemi correlati