2009-06-03 19 views
8

È possibile rilevare ripetizioni di numeri con un'espressione regolare?Espressione regolare per rilevare la ripetizione all'interno di una stringa

Quindi, ad esempio, se avessi la seguente stringa "034503450345", sarebbe possibile abbinare la sequenza ripetuta 0345? Ho la sensazione che questo sia oltre lo scopo della regex, ma ho pensato che avrei chiesto comunque di vedere se ho perso qualcosa.

+1

Che lingua/piattaforma stai usando? –

+0

Sto usando C#. Tutto quello di cui avevo bisogno era la regex, quindi ho implementato la soluzione di RichieHindle e l'ho già verificata rispetto ai miei dati di test! Ho anche imparato molto dall'espressione regolare di Peter Boughton. Grazie a tutti e due! –

+0

@MarkWithers Mi sto occupando dello stesso problema. Puoi per favore essere più concreto e dirmi qualcosa di più sulla tua soluzione? Grazie – user2179427

risposta

9

Sì, è possibile - ecco un banco di prova Python

import re 
print re.search(r"(\d+).*\1", "8034503450345").group(1) 
# Prints 0345 

L'espressione regolare dice "trovare qualche sequenza di cifre, quindi qualsiasi quantità di altre cose, poi di nuovo la stessa sequenza."

In una nota a malapena-correlata, ecco una delle mie espressioni regolari preferiti - un primo rivelatore di serie:

import re 
for i in range(2, 100): 
    if not re.search(r"^(xx+)\1+$", "x"*i): 
     print i 
+0

Il tuo rilevatore numero primo trova 0 e 1 come primi :-) – balpha

+0

Qualsiasi idea perché il seguente esempio è * solo * corrispondente a '8' e non' 0345'? In [18]: foo = re.search (r "(\ d +) * \ 1", "80345824103452420345") In [19]: foo.groups() Out [19]: ('8 ',) –

+0

@balpha: buon pont - risolto. 8-) – RichieHindle

19

Questa espressione corrisponderà uno o più gruppi di ripetizione:

(.+)(?=\1+) 


Ecco la stessa espressione analizzata, (utilizzando commenti in modo che possa essere ancora utilizzata direttamente come espressione regolare).

(?x) # enable regex comment mode 
( # start capturing group 
.+ # one or more of any character (excludes newlines by default) 
)  # end capturing group 
(?= # begin lookahead 
\1+ # match one or more of the first capturing group 
)  # end lookahead 


per abbinare un modello specifico, modificare la .+ al sistema scelto, per esempio \d+ per uno o più numeri o \d{4,} per abbinare 4 o più numeri.

Per abbinare un numero specifico del motivo, modificare \1+, ad esempio \1{4} per quattro ripetizioni.

Per consentire la ripetizione di non essere uno accanto all'altro, è possibile aggiungere .*? all'interno del lookahead.

+1

Grande spiegazione +1 – ichiban

+0

Un buon esempio, spiegato molto bene –

+0

Grande spiegazione. Eccellente estensione Grazie!! +1 – Toto

8

solo per aggiungere una nota per la (corretta) risposta da RichieHindle:

notare che, mentre l'attuazione regexp di Python (e molti altri, come Perl) può fare questo, questo non è più un'espressione regolare in senso stretto della parola.

L'esempio non è un linguaggio normale, quindi non può essere gestito da una pura espressione regolare. Vedi per es. l'eccellente Wikipedia article per i dettagli.

Sebbene questo sia principalmente di interesse accademico, ci sono alcune conseguenze pratiche. Le vere espressioni regolari possono offrire garanzie migliori per i tempi di esecuzione massimi rispetto a questo caso. Quindi potresti avere problemi di prestazioni ad un certo punto.

Per non dire che non è una buona soluzione, ma dovresti capire che sei al limite di ciò che le espressioni regolari (anche in forma estesa) sono in grado, e potresti prendere in considerazione altre soluzioni in caso di problemi .

+0

Lettura molto interessante, grazie per quello. –

2

Questo è il codice C#, che utilizza il costrutto backreference per trovare cifre ripetute. Funzionerà con 034503450345, 123034503450345, 034503450345345, 232034503450345423. L'espressione regolare è molto più semplice e chiara da comprendere.

/// <summary> 
/// Assigns repeated digits to repeatedDigits, if the digitSequence matches the pattern 
/// </summary> 
/// <returns>true if success, false otherwise</returns> 
public static bool TryGetRepeatedDigits(string digitSequence, out string repeatedDigits) 
{ 
    repeatedDigits = null; 

    string pattern = @"^\d*(?<repeat>\d+)\k<repeat>+\d*$"; 

    if (Regex.IsMatch(digitSequence, pattern)) 
    { 
     Regex r = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled); 
     repeatedDigits = r.Match(digitSequence).Result("${repeat}"); 
     return true; 
    } 
    else 
     return false; 
} 
+0

Molto bello! Mi piace l'uso del gruppo indicato. Codice di qualità della produzione, commentato e pronto per essere copiato. Grazie mille! –

+0

"Pronto per essere copiato": D .. Mi piace !!!! –

0

Uso ripetizione regex: bar {2,} cerca testo con due o più bar: barbar barbarbar ...

Problemi correlati