2015-02-28 15 views
13

Dopo ore di ricerca ho deciso di fare questa domanda. Perché questa espressione regolare: ^(dog).+?(cat)? non funziona come penso che dovrebbe funzionare (catturare il primo cane e gatto se ce n'è uno)? Cosa mi manca qui?Gruppo di acquisizione regex opzionale?

dog, cat 
dog, dog, cat 
dog, dog, dog 

risposta

17

Il motivo per cui non si ottiene un optional cat dopo una riluttanza qualificato .+? è che è sia facoltativo e non ancorato: il motore non è costretto a fare quella partita, perché può legalmente trattare la cat come "coda" della sequenza .+?.

Se yo ancorare il gatto alla fine della stringa, cioè utilizzare ^(dog).+?(cat)?$, si otterrebbe un match, però:

Pattern p = Pattern.compile("^(dog).+?(cat)?$"); 
for (String s : new String[] {"dog, cat", "dog, dog, cat", "dog, dog, dog"}) { 
    Matcher m = p.matcher(s); 
    if (m.find()) { 
     System.out.println(m.group(1)+" "+m.group(2)); 
    } 
} 

Questo stampa (demo 1)

dog cat 
dog cat 
dog null 

Do capita di sapere come affrontarlo nel caso ci sia qualcosa dopo il gatto?

Si può trattare con esso costruendo un'espressione più complicato che corrisponde nulla, tranne cat, in questo modo:

^(dog)(?:[^c]|c[^a]|ca[^t])+(cat)? 

Ora il cat potrebbe accadere in qualsiasi punto della stringa, senza un ancoraggio (demo 2).

+3

Grazie. Ti capita di sapere come affrontarlo nel caso in cui ci sia qualcosa dopo il gatto? Ad esempio: 'cane, cane, gatto, blah'. Voglio catturare solo il primo cane e il gatto opzionale (ci può essere al massimo un gatto). – forsajt

+1

piacerebbe vedere questa risposta –

4

@ risposta di dasblinkenlight è grande, ma ecco un'espressione regolare che migliora la seconda parte di esso, quando lui/lei ha chiesto

Ti capita di sapere come trattare con esso in caso ci sia qualcosa dopo gatto?

L'espressione regolare ^(dog)(.+(cat))? richiederebbe di acquisire il gruppo n. 3 invece di 2 per ottenere il gatto opzionale, ma funziona altrettanto bene senza i trucchi char-by-char.

Ed ecco the demo (che, ancora una volta, è biforcuta da @ di dasblinkenlight demo che mi ha permesso di armeggiare e trovare questa soluzione, grazie ancora!)

+0

Funziona anche con un gruppo non catturante come^(cane) (?:. + (Gatto))? quindi non hai un gruppo di acquisizione extra –

2

@ estensione del Figha può essere esteso un po 'più ancora, di non fare il seconda cattura non necessaria.

Utilizzare ?: per creare una parte di bracketing di un'espressione regolare non catturabile. Quindi la regex diventa: ^(dog)(?:.+(cat))?

Anche in questo caso, ecco lo extended demo e lo regex test.

Problemi correlati