2011-11-18 25 views
10

Soy horrible en expresiones RegEx y simplemente no las uso con la frecuencia suficiente para recordar la sintaxis entre usos.Regex para que coincida cuando una cadena está presente dos veces

Estoy usando grepWin para buscar mis archivos. Necesito hacer una búsqueda que devolverá los archivos que tienen una cadena dada dos veces.

Así, por ejemplo, si yo estaba buscando en la palabra "cómo", a continuación, presentar uno no coincida:

Hola
¿Cómo estás hoy?

pero presentar dos sería:

Hola
¿Cómo estás hoy?

Estoy bien, ¿cómo estás?

¿Alguien sabe cómo hacer un RegEx que coincida con eso?

+1

Si la cadena de búsqueda tiene que ser una variable, esto no es posible con Regex. Necesitarías combinarlo con un lenguaje de scripting. Si no necesita ser variable, esta expresión regular sería: 'cómo estás. * Cómo estás ' – Jeff

+1

@Jeff Es posible hacer referencia a un grupo coincidente en una expresión regular de JavaScript:'/(abc) \ 1/'coincide con' abcabc', pero no con 'abc'. –

+0

¿Debe coincidir solo si aparece "cómo" _exactly_ dos veces? ¿Qué pasa si aparece tres o más veces? – Wiseguy

Respuesta

13

algo como esto (depende del lenguaje y su tarea específica)

\(how.*){2}\ 

Editar: acuerdo con @CodeJockey

\^(([^h]|h[^o]|ho[^w])*how([^h]|h[^o]|ho[^w])*){2,2}$\ 

(a ser más complicado) @CodeJockey: Gracias para comentarios

+3

esto obtendrá archivos con 'cómo' dos o más veces, pero ** no excluye ** archivos con tres o más ocurrencias –

+0

sí, tiene razón – VMykyt

+1

@CodeJockey Así es como lo leí. Me preguntaba si el que preguntaba quiso decir "exactamente" dos veces. – Wiseguy

1

Esto es mucho más difícil de lo que originalmente pensé que sería, y requiere de búsqueda hacia atrás de longitud variable, que grepWin no soporta ...

esta expresión:

(?<!blah.{0,99999})blah(?=.*?blah)(?!.*blah.*blah) 

se utilizó con éxito en Eclipse, usando la opción "Buscar> Archivo" de diálogo para excluir archivos con una y tres instancias de blah y para incluir archivos con exactamente dos instancias de blah.

Eclipse no permite .* en lookbehind, así que usé .{0,99999} en su lugar.

Es posible, con la herramienta adecuada, pero no es bonito hacer que funcione con grepWin (ver respuesta arriba). ¿Puede utilizar otras herramientas (como Eclipse) y qué desea hacer con los archivos después?

+0

Si lookbehinds es un problema, lo hice solo con lookaheads. – Wiseguy

+0

Sí, no me molesté una vez que probé la solución de @ VMykyt en el producto solicitado y funcionó (especialmente sin ningún interés aparente del OP). Cuando estaba trabajando en esto, mi cerebro de alguna manera perdió temporalmente la idea del anclaje de principio de línea o cadena, que debería permitirlo sin mirar hacia atrás: D –

+0

@Wiseguy Me gusta que su solución use todo Sin embargo, aunque no sería demasiado difícil de agregar, nadie ha explicado el hecho de que el OP puede querer emparejar solo los archivos con dos instancias de cómo, pero permitir "howitzer" o "de alguna manera" o incluso "ducharse" cualquier cantidad de veces –

4

No sé lo que grepWin admite, pero esto es lo que se me ocurrió para hacer que algo coincida exactamente dos veces.

/^((?!how).)*how((?!how).)*how((?!how).)*$/ 

Explicación:

/^    # start of subject 
    ((?!how).)* # any text that does not contain "how" 
    how   # the word "how" 
    ((?!how).)* # any text that does not contain "how" 
    how   # the word "how" 
    ((?!how).)* # any text that does not contain "how" 
$/    # end of subject 

Esto asegura que se encuentran dos "cómo" s, pero los textos entre el "cómo" s y a cada lado de ellos no contienen "cómo".

Por supuesto, puede sustituir cualquier cadena por "cómo" en la expresión.


Si usted quiere "simplificar" sólo escribir la expresión de búsqueda en dos ocasiones, puede utilizar referencias hacia atrás así:

/^(?:(?!how).)*(how)(?:(?!\1).)*\1(?:(?!\1).)*$/ 

Refiddle with this expression

Explicación:
añadí ?: para hacer la texto negativo de lookaheads sin captura. Luego agregué paréntesis alrededor del how normal para convertirlo en un subpatrón de captura (el primero y el único).

he tenido que incluir "cómo" de nuevo en la primera búsqueda hacia delante porque es una búsqueda negativa hacia delante (es decir, cualquier captura que no contener "cómo") y el capturado "cómo" no se refleja todavía en ese punto.

Cuestiones relacionadas