2009-03-04 27 views

Respuesta

182

Se puede usar un afirmación de preanálisis:

(?!999)\d{3} 

Este ejemplo coincide con tres dígitos que no sean 999.


Pero si le sucede no tener una aplicación de expresiones regulares con esta característica (ver Comparison of Regular Expression Flavors), es probable que construir una expresión regular con las características básicas de su propio.

Una expresión regular compatible con la sintaxis básica sólo sería:

[0-8]\d\d|\d[0-8]\d|\d\d[0-8] 

Esto también se encontró ningún secuencia de tres dígitos que no es 999.

+1

Look-ahead no es una sintaxis estándar de expresión regular, es una extensión Perl, solo funcionará en Perl, PCRE (Perl-Compatible RegEx) u otras implementaciones no estándar – Juliano

+9

Puede no ser estándar, pero no la mayoría de los idiomas modernos lo soportan? ¿Qué idioma * no * admite look-aheads en estos días? –

+0

Eso es verdad. Pero la mayoría de los sabores de expresiones regulares admiten esta función (consulte ). – Gumbo

15

Partido contra el patrón y el uso de la lengua de acogida para invertir el resultado booleano del partido. Esto será mucho más legible y mantenible.

+1

Entonces acabo con (~ A o B) en lugar de (A y ~ B) .. no resuelve mi problema – notnot

+1

Pseudo-código: totest cadena; if (! toTest.matches (A) y toTest.matches (B)) {...} –

+0

que debería haber sido más claro - las piezas no son completamente independientes. Si A coincide con una parte de la cadena, nos preocupamos si ~ B coincide con el resto (pero no necesariamente con todo). Esto fue para la función FindSit de la línea de comandos de Windows, que encontré restringido a expresiones regulares verdaderas, por lo tanto, punto discutible. – notnot

4

El complemento de un idioma normal también es un idioma normal, pero para construirlo debe compilar el DFA para el idioma normal, y hacer cualquier cambio de estado válido en un error. Ver this para un ejemplo. Lo que la página no dice es que convirtió /(ac|bd)/ en /(a[^c]?|b[^d]?|[^ab])/. La conversión de un DFA a una expresión regular no es trivial. Es más fácil si puede usar la expresión regular sin cambios y cambiar la semántica en el código, como se sugirió antes.

+2

Si tuviera que lidiar con expresiones regex reales, entonces todo esto sería discutible. Regex ahora parece referirse al nebuloso espacio CSG-ish (?) De coincidencia de patrones que admite la mayoría de los lenguajes. Como necesito hacer coincidir (A y ~ B), no hay forma de eliminar la negación y aún así hacerlo todo en un solo paso. – notnot

+0

Lookahead, como se describió anteriormente, lo habría hecho si findstr hiciera algo más allá de las verdaderas expresiones regulares de DFA. Todo es extraño y no sé por qué tengo que hacer este estilo de línea de comandos (lote ahora). Es solo otro ejemplo de mis manos atadas. – notnot

+1

@notnot: ¿Está utilizando findstr de Windows? Entonces solo necesitas/v. Me gusta: findstr Un archivo de entrada | findstr/v B> archivoSalida.txt El primero coincide con todas las líneas con A, el segundo coincide con todas las líneas que no tienen B. – Juliano

1

patrón - re

str.split(/re/g) 

volverá todo excepto el patrón.

prueba here

+0

Probablemente quiera mencionar que necesita unirse nuevamente. – tomdemuyt

+0

Un enfoque similar es usar 'reemplazar' ' str.replace (/ re/g, '') ', luego no hay necesidad de volver a unirlos. también si arrojas un buen trailing \ s? como 'str.replace (/ \ re \ s?/g, '')' luego se deshace de los espacios duplicados que tendría de algo reemplazado en el medio de una cadena – jakecraige

0
(B)|(A) 

a continuación, utilizar lo que el grupo 2 capturas ...

+0

Necesita * capturar * no B, su objetivo no es simplemente ignorar todos los patrones B. – hexicle

+0

Quizás sea incorrecto aquí, pero era exactamente lo que estaba buscando – user3473534

25

Si desea hacer coincidir una palabra A en una cadena y no para que coincida con una palabra B. Por ejemplo: Si usted tiene un texto:

1. I have a two pets - dog and a cat 
2. I have a pet - dog 

Si desea buscar líneas de texto que tiene un perro a una mascota y no tiene gato puede utilizar esta expresión regular:

^(?=.*?\bdog\b)((?!cat).)*$ 

encontrará solamente segunda línea:

2. I have a pet - dog 
+0

No lo mencionó en la pregunta, pero el OP está usando el comando 'findstr' de DOS. Ofrece solo un pequeño subconjunto de las capacidades que espera encontrar en una herramienta de expresiones regulares; lookahead no está entre ellos. (Acabo de agregar la etiqueta [tag: findstr].) –

+2

hm, sí, encontré ahora en uno de sus comentarios en las publicaciones. Vi a Regex en el título. De todos modos, si alguien encuentra esta publicación cuando busca la misma expresión regular, como yo lo hice, tal vez podría ser útil a alguien :) gracias por los comentarios – Aleks

+1

Gracias Aleks. Tal como lo imaginaste, me crucé con esta pregunta por el título y me respondiste muy bien. – Hagelt18

7

notnot, resucitar a esta antigua pregunta porque tenía una solución simple que no era' t mencionado. (Encontró su pregunta mientras investigaba un regex bounty quest.)

Me enfrento a una situación en la que tengo que hacer coincidir un (A y ~ B) patrón.

La expresión regular básica para esto es terriblemente simple: B|(A)

Sólo ignora los partidos en general y examinar las capturas del grupo 1, que contendrá A.

Un ejemplo (con todas las renuncias de unos análisis de HTML en regex): a es dígitos, B es dígitos dentro de <a tag

la expresión regular: <a.*?<\/a>|(\d+)

Demo (mirar en el Grupo 1 en el panel inferior derecho)

Referencia

How to match pattern except in situations s1, s2, s3

How to match a pattern unless...

0

Mi respuesta aquí podría resolver su problema así:

https://stackoverflow.com/a/27967674/543814

  • En lugar de Reemplazar, usaría Match.
  • En lugar del grupo $1, leería el grupo $2.
  • Grupo $2 se hizo no capturar allí, lo que evitaría.

Ejemplo:

Regex.Match("50% of 50% is 25%", "(\d+\%)|(.+?)");

El primer grupo de captura especifica el patrón que se desea evitar. El último grupo de captura captura todo lo demás. Simplemente lea ese grupo, $2.

Cuestiones relacionadas