Quale regex può corrispondere alle sequenze dello stesso personaggio?

Un amico mi ha chiesto questo e sono rimasto perplesso: esiste un modo per creare un’espressione regolare che corrisponda a una sequenza dello stesso personaggio? Ad esempio, corrisponde a “aaa”, “bbb”, ma non “abc”?

m|\w{2,3}| 

Non farebbe il trucco in quanto corrisponderebbe a ‘abc’.

 m|a{2,3}| 

Non farebbe il trucco in quanto non corrisponderebbe a ‘bbb’, ‘ccc’, ecc.

Cosa certa! Raggruppamento e riferimenti sono i tuoi amici:

 (.)\1+ 

Corrisponde a 2 o più occorrenze dello stesso personaggio. Solo per i caratteri costituenti della parola, utilizzare \w anziché . , cioè:

 (\w)\1+ 

Notare che in Perl 5.10 abbiamo anche delle notazioni alternative per i backreferences.

 foreach (qw(aaa bbb abc)) { say; say ' original' if /(\w)\1+/; say ' new way' if /(\w)\g{1}+/; say ' relative' if /(\w)\g{-1}+/; say ' named' if /(?'char'\w)\g{char}+/; say ' named' if /(?\w)\k+/; } 

Questo corrisponderà a più di \ w , come @@@:

 /(.)\1+/ 

Ecco a cosa servono le backreferences.

 m/(\w)\1\1/ 

farà il trucco.

Ciò è anche ansible usando espressioni regolari pure (cioè quelle che descrivono le lingue regolari – non le espressioni regolari di Perl). Sfortunatamente, significa un’espressione regolare la cui lunghezza è proporzionale alla dimensione dell’alfabeto, ad esempio:

 (a* + b* + ... + z*) 

Dove a … z sono i simboli dell’alfabeto finito.

Quindi Perl regexps, sebbene sia un superset di pure espressioni regolari, ha sicuramente i suoi vantaggi anche quando vuoi semplicemente usarli per pura espressione regolare!

Rispondere alla mia domanda, ma l’ho capito:

 m|(\w)\1+| 

Se stai usando Java e trovi caratteri duplicati in una determinata stringa, ecco il codice,

 public class Test { public static void main(String args[]) { String s = "abbc"; if (s.matches(".*([a-zA-Z])\\1+.*")) { System.out.println("Duplicate found!"); } else { System.out.println("Duplicate not found!"); } } 

}