2012-02-07 14 views
5

È possibile sottrarre un carattere corrispondente in una classe di caratteri?Pattern: come sottrarre il carattere abbinato nella classe di caratteri?

Java docs stanno avendo esempi di classi di personaggi con la sottrazione:

[a-z&&[^bc]] - a through z, except for b and c: [ad-z] (subtraction) 
[a-z&&[^m-p]] - a through z, and not m through p: [a-lq-z](subtraction) 

voglio scrivere modello, che corrisponde a due coppie di caratteri di parola, quando le coppie non sono gli stessi:

1) "aaaa123" - should NOT match 
2) "aabb123" - should match "aabb" part 
3) "aa--123" - should NOT match 

I Sono vicino al successo con il seguente schema:

([\w])\1([\w])\2 

ma ovviamente non funziona nel caso 1, quindi devo sottrarre la corrispondenza del primo gruppo. Ma quando provo a fare questo:

Pattern p = Pattern.compile("([\\w])\\1([\\w&&[^\\1]])\\2"); 

io sono sempre un'eccezione:

Exception in thread "main" java.util.regex.PatternSyntaxException: Illegal/unsupported escape sequence near index 17 
([\w])\1([\w&&[^\1]])\2 
       ^
    at java.util.regex.Pattern.error(Pattern.java:1713) 

Così sembra che non funziona con i gruppi, ma solo con la messa in vendita di caratteri specifici. Il seguente schema si compila senza problemi:

Pattern p = Pattern.compile("([\\w])\\1([\\w&&[^a]])\\2"); 

C'è qualche altro modo per scrivere tale modello?

risposta

3

Usa

Pattern p = Pattern.compile("((\\w)\\2(?!\\2))((\\w)\\4)"); 

vostri personaggi saranno in gruppi 1 e 3.

Questo funziona utilizzando un lookahead negativo, per assicurarsi che il carattere che segue il secondo carattere nel primo gruppo di caratteri sia un carattere diverso.

1

Si sta utilizzando lo strumento sbagliato per il lavoro. Con tutti i mezzi usa una regex per rilevare coppie di coppie di caratteri, ma puoi semplicemente usare != per verificare se i caratteri all'interno delle coppie sono gli stessi. Seriamente, non c'è alcun motivo per fare di tutto il in un'espressione regolare: si tratta di codice illeggibile e non portabile e non ti porta alcun vantaggio se non quello di "essere alla moda".

+1

Le espressioni regolari effettivamente fare uno sguardo fresco: http: // xkcd.it/208/ – flesk

+0

@ Kilian: questo modello è solo uno dei tanti (ce ne sono anche molti semplici) per abbinare le parti di stringa - quindi non è solo per essere "cool" come dici tu - il sistema itera attraverso i pattern e li abbina. .. Se dovessi andare con il tuo modo suggerito - Avrei ancora più soluzione "non cool" in quanto avrei bisogno di aggiungere "ifs" personalizzati per uno o l'altro caso ... – Laimoncijus

+0

@flesk: molto bello, +1 da me ! :) – Laimoncijus

1

Prova questa

String regex = "(\\w)\\1(?!\\1)(\\w)\\2"; 
Pattern pattern = Pattern.compile(regex); 

(?!\\1) è un negative lookahead, assicura che il contenuto di \\1 non segue

mio codice di prova

String s1 = "aaaa123"; 
String s2 = "aabb123"; 
String s3 = "aa--123"; 
String s4 = "123ccdd"; 

String[] s = { s1, s2, s3, s4 }; 
String regex = "(\\w)\\1(?!\\1)(\\w)\\2"; 

for(String a : s) { 
    Pattern pattern = Pattern.compile(regex); 
    Matcher matcher = pattern.matcher(a); 

    if (matcher.find()) 
     System.out.println(a + " ==> Success"); 
    else 
     System.out.println(a + " ==> Failure"); 
} 

L'uscita

aaaa123 ==> La mancata
aabb123 ==> Successo
aa - 123 ==> Failure
123ccdd ==> Successo

Problemi correlati