2010-05-12 23 views
77

Sono un principiante espressione regolare, e non riesco a capire come scrivere una singola espressione regolare che avrebbe "match" Alcune parole consecutive duplicati quali:espressione regolare per consecutivi le parole duplicate

Parigi in la primavera.

Non che quello è correlato.

Perché ridi? Sono my my espressioni regolari che male ??

Esiste una singola espressione regolare che corrisponderà a TUTTE le stringhe in grassetto sopra?

+3

No, questo non è compito. Mi vergogno dell'umanità per il fatto che alcune persone usano StackOverflow per fare i compiti per loro. – Joshua

+4

@poly: Quella non era una "accusa", ma una domanda calma e normale che perfettamente può prendere un "no" come risposta. @Joshua: Sì, alcune persone (non troppo poche) lasciano che questo sito faccia i compiti per loro. Ma fare domande a casa non è una brutta cosa da fare su SO, quando sono taggati come tali. Di solito lo stile delle risposte cambia da "ecco la soluzione" a "ecco alcune cose a cui non hai pensato", e questa è una buona cosa. Qualcuno deve cercare di mantenere la distinzione, nel suo caso sono stato io, e altrove "altre persone" fanno la stessa cosa. È tutto. – Tomalak

+7

Spero di non vedere mai una domanda del tipo "Sembra una domanda sul posto di lavoro." e poi la gente sosterrà se lo straripamento dello stack sta facendo il lavoro di qualcuno. – marcio

risposta

87

Prova questa espressione regolare:

\b(\w+)\s+\1\b 

Qui \b è un confine di parola e \1 riferimenti alla partita catturato del primo gruppo.

+1

Mi fa meravigliare; è possibile fare anche '\ 0'? (Dove '\ 0' è l'intera regex, fino al punto corrente O dove' \ 0' si riferisce all'intera espressione regolare) – Pindatjuh

+0

@Pindatjuh: No, non penso perché questa sub-partita sarebbe anche parte di l'intera partita. – Gumbo

+0

Almeno funziona sul motore regex utilizzato nella finestra di dialogo di ricerca/sostituzione di Eclipse. –

3

No. Questa è una grammatica irregolare. Potrebbero esserci espressioni regolari specifiche per linguaggio/motore che è possibile utilizzare, ma non esiste un'espressione regolare universale che possa farlo.

+12

Pur essendo corretto in senso stretto, credo che non ci sia più un motore regex in uso serio che non supporti raggruppamenti e riferimenti. – Tomalak

4

La libreria PCRE diffuso in grado di gestire tali situazioni (non raggiungere la la stesso con motori regex POSIX-compliant, però):

(\b\w+\b)\W+\1 
+0

Hai bisogno di qualcosa per abbinare i caratteri * tra * le due parole, come' \ W + '. '\ b' non lo farà, perché non consuma alcun personaggio. –

+0

Molte grazie, risolto. – soulmerge

+0

Ciò potrebbe potenzialmente causare corrispondenze false positive in casi come '... the these problems ...'. Questa soluzione non è affidabile quanto la struttura generale del modello di Gumbo che implementa sufficientemente i confini delle parole. – mickmackusa

15

Credo che questa regex gestisce più situazioni:

/(\b\S+\b)\s+\b\1\b/ 

Una buona selezione di stringhe di prova può essere trovato qui: http://callumacrae.github.com/regex-tuesday/challenge1.html

+0

Ottimo, funziona con apostrofi/trattini/ecc. anche - grazie! – JoeRocc

+0

per il collegamento challenge1, cosa si inserisce nell'area di sostituzione per utilizzare la parola raggruppata? Provato '\ 0' ma non funziona. – uptownhr

+1

Non catturerà i triplicati (o più), non quando uno dei dupli/triplici è alla fine della stringa – Nico

2

L'esempio in Javascript: Le parti buone possono essere adattati per fare questo:

var doubled_words = /([A-Za-z\u00C0-\u1FFF\u2800-\uFFFD]+)\s+\1(?:\s|$)/gi; 

\ B utilizza \ w per confini di parola, dove \ w è equivalente a [0-9A-Z_A-z]. Se non ti dispiace questa limitazione, la risposta accettata va bene.

2

Questa è l'espressione regolare che uso per rimuovere le frasi duplicati nel mio tic bot:

(\S+\s*)\1{2,} 

(\S+\s*) cerca qualsiasi stringa di caratteri che non è uno spazio, seguita spazi.

\1{2,} quindi cerca più di 2 istanze di quella frase nella stringa corrispondente. Se ci sono 3 frasi identiche, corrisponde.

+0

Questa risposta è fuorviante. Non caccia i duplicati, caccia le sottostringhe con 3 o più occorrenze. Inoltre non è molto robusto a causa di '\ s *' nel gruppo di cattura. Vedi questa dimostrazione: https://regex101.com/r/JtCdd6/1 – mickmackusa

+0

Inoltre casi estremi (testo a bassa frequenza) producono corrispondenze false positive. Per esempio. "Ho detto" oioioi "che è un cattivo padrone!' Su 'oioioi' e' sss' – mickmackusa

1

Questa espressione (ispirato da Mike, sopra) sembra catturare tutti i duplicati, triplicati, ecc, compresi quelli alla fine della stringa, che la maggior parte degli altri non lo fanno:

/(^|\s+)(\S+)(($|\s+)\2)+/g, "$1$2") 

I conoscere la domanda posta in modo che corrisponda duplica solo, ma un triplice copia si trova a soli 2 duplicati accanto all'altro :)

In primo luogo, ho messo (^|\s+) per assicurarsi che comincia con una parola piena, altrimenti "bistecca del bambino" sarebbe andato a "child'steak" (le "s" corrispondono). Quindi, corrisponde a tutte le parole complete ((\b\S+\b)), seguito da una fine di stringa ($) o da un numero di spazi (\s+), il tutto ripetuto più volte.

ho provato come questo e ha funzionato bene:

var s = "here here here  here is ahi-ahi ahi-ahi ahi-ahi joe's joe's joe's joe's joe's the result result  result"; 
print(s.replace(/(\b\S+\b)(($|\s+)\1)+/g, "$1"))   
--> here is ahi-ahi joe's the result 
+0

Ho problemi a riscriverlo in PHP, è fondamentale ottenere una singola copia del duplicato corrispondente sostituendo ogni occorrenza di duplicati/triplicati ecc. .Finora ho: preg_replace ('/ (^ | \ s +) (\ S +) (($ | \ s +) \ 2) +/im', '$ 0', $ stringa); – AdamJones

0

Utilizzare questo nel caso in cui si desidera che il controllo maiuscole e minuscole per le parole duplicate.

(?i)\\b(\\w+)\\s+\\1\\b 
+0

L'utilizzo del modificatore di modello senza distinzione tra maiuscole e minuscole non è utile per il modello. Non ci sono intervalli di lettere per l'impatto della bandiera. – mickmackusa

+0

Questo è effettivamente un duplicato della risposta accettata e non aggiunge alcun valore alla pagina. Si prega di prendere in considerazione la rimozione di questa risposta per ridurre l'espansione della pagina. – mickmackusa

3

Prova questo con sotto RE

  • \ b inizio del limite di parola parola
  • carattere \ W + qualsiasi parola
  • \ 1 stessa parola ha trovato già
  • \ b fine della parola
  • () * Ripetuto di nuovo

    public static void main(String[] args) { 
    
        String regex = "\\b(\\w+)(\\b\\W+\\b\\1\\b)*";// "/* Write a RegEx matching repeated words here. */"; 
        Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE/* Insert the correct Pattern flag here.*/); 
    
        Scanner in = new Scanner(System.in); 
    
        int numSentences = Integer.parseInt(in.nextLine()); 
    
        while (numSentences-- > 0) { 
         String input = in.nextLine(); 
    
         Matcher m = p.matcher(input); 
    
         // Check for subsequences of input that match the compiled pattern 
         while (m.find()) { 
          input = input.replaceAll(m.group(0),m.group(1)); 
         } 
    
         // Prints the modified sentence. 
         System.out.println(input); 
        } 
    
        in.close(); 
    } 
    
0

Dal momento che alcuni sviluppatori stanno arrivando a questa pagina in cerca di una soluzione che non solo elimina duplicati stringhe che non sono spazi consecutivi, ma triplicati e al di là, ti faccio vedere il modello adattato.

Pattern: /(\b\S+)(?:\s+\1\b)+/ (Pattern Demo)
Sostituire: $1 (sostituisce il match fullstring con il gruppo di cattura # 1)

Questo modello corrisponde avidamente un "tutto" stringa senza spazi, quindi richiede una o più copie di la sottostringa corrispondente che può essere delimitata da uno o più caratteri di spaziatura (spazio, tab, newline, ecc.).

In particolare:

  • \b (limite di parola) personaggi sono di vitale importanza per garantire le parole parziali non corrispondono.
  • Il secondo parentetico è un gruppo non acquisibile, poiché questa sottostringa a larghezza variabile non deve essere catturata, ma solo abbinata/assorbita.
  • il + (uno o più quantificatori) sul gruppo non acquisibile è più appropriato di * perché * "disturberà" il motore regex per catturare e sostituire le occorrenze di singleton - questo è un disegno di progettazione sprecone.

* nota se si hanno a che fare con frasi o stringhe di input con segni di punteggiatura, il modello dovrà essere ulteriormente rifinito.

+0

@AdamJones utilizza questo modello nel progetto php. La risposta di Nico ha una sintassi non necessaria. – mickmackusa

Problemi correlati