Expresión regular para palabras consecutivas duplicadas

Soy un novato de expresiones regulares, y no puedo entender cómo escribir una sola expresión regular que “coincida” con palabras duplicadas consecutivas, como:

París en la spring.

No es que eso esté relacionado.

¿Por qué te ríes? ¿Son mis expresiones regulares ESO malo?

¿Hay una sola expresión regular que coincida con TODAS las cadenas en negrita de arriba?

Prueba esta expresión regular:

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

Aquí \b es un límite de palabra y \1 referencia al emparejamiento capturado del primer grupo.

Creo que esta expresión regular maneja más situaciones:

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

Una buena selección de cadenas de prueba se puede encontrar aquí: http://callumacrae.github.com/regex-tuesday/challenge1.html

La biblioteca PCRE ampliamente utilizada puede manejar tales situaciones (sin embargo, no logrará lo mismo con los motores regex que cumplen con POSIX):

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

No. Esa es una gramática irregular. Puede haber expresiones regulares específicas del motor / idioma que pueda usar, pero no existe una expresión regular universal que pueda hacer eso.

Prueba esto con RE a continuación

  • \ b inicio de la palabra límite de palabra
  • \ W + cualquier personaje de palabra
  • \ 1 misma palabra emparejada ya
  • \ b fin de palabra
  • () * Repitiendo de nuevo

     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(); } 

El ejemplo en Javascript: The Good Parts se puede adaptar para hacer esto:

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

\ b usa \ w para límites de palabras, donde \ w es equivalente a [0-9A-Z_a-z]. Si no te importa esa limitación, la respuesta aceptada está bien.

Esta es la expresión regular que uso para eliminar frases duplicadas en mi bot de contracción:

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

(\S+\s*) busca cualquier cadena de caracteres que no sea un espacio en blanco, seguido de un espacio en blanco.

\1{2,} luego busca más de 2 instancias de esa frase en la cadena para unir. Si hay 3 frases que son idénticas, coincide.

Esta expresión (inspirada en Mike, arriba) parece captar todos los duplicados, triplicados, etc., incluidos los que están al final de la cadena, que la mayoría de los demás no:

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

Sé que la pregunta que se pide coincide con los duplicados solamente, pero un triplicado es solo 2 duplicados uno al lado del otro 🙂

Primero, puse (^|\s+) para asegurarme de que comience con una palabra completa, de lo contrario “filete de niño” iría a “niño” (las “s” coincidirían). Luego, coincide con todas las palabras completas ( (\b\S+\b) ), seguido por un final de cadena ( $ ) o una cantidad de espacios ( \s+ ), el total se repite más de una vez.

Lo intenté así y funcionó bien:

 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 

Dado que algunos desarrolladores están llegando a esta página en busca de una solución que no solo elimine las subcadenas consecutivas que no sean de espacios en blanco, sino que tripliquen y más allá, mostraré el patrón adaptado.

Patrón: /(\b\S+)(?:\s+\1\b)+/ ( Demo de patrón )
Reemplazar: $1 (reemplaza la coincidencia de cadena completa con el grupo de captura n.º 1)

Este patrón coincide con una subcadena “no completa” en espacios en blanco, luego requiere una o más copias de la subcadena coincidente que puede estar delimitada por uno o más caracteres en blanco (espacio, tabulación, nueva línea, etc.).

Específicamente:

  • \b (límite de palabra) son vitales para garantizar que las palabras parciales no coincidan.
  • El segundo entre paréntesis es un grupo que no captura, porque esta subcadena de ancho variable no necesita ser capturada, solo emparejada / absorbida.
  • el + (uno o más cuantificadores) en el grupo que no captura es más apropiado que * porque * “molestará” al motor de expresiones regulares para capturar y reemplazar las ocurrencias de singleton; este es un diseño de patrón derrochador.

* tenga en cuenta si se trata de oraciones o cadenas de entrada con signos de puntuación, entonces el patrón tendrá que ser más refinado.

Use esto en caso de que desee una verificación insensible a las mayúsculas y minúsculas de las palabras duplicadas.

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

Aquí hay uno que atrapa varias palabras varias veces:

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

Regex to Strip 2+ palabras duplicadas (palabras consecutivas / no consecutivas)

Pruebe esta expresión regular que puede capturar 2 o más palabras duplicadas y solo deja una palabra atrás. Y las palabras duplicadas ni siquiera necesitan ser consecutivas .

 /(\b\w+\b)(?=\b.*\1\b)/ig 

Aquí, \b se usa para Word Boundary,? ?= Se usa para un lookahead positivo, y \1 se usa para back-referencing.

Fuente de ejemplo