2010-08-25 8 views
12

¿Cómo se podría escribir una expresión regular que coincida con un patrón que puede contener comillas, pero si lo hace, debe tener comillas coincidentes al principio y al final?¿Cómo puedo unir un patrón con comillas circundantes opcionales?

"?(pattern)"? 

No funcionará porque permitirá que los patrones comiencen con una cita pero no terminen con una.

"(pattern)"|(pattern) 

Funciona, pero es repetitivo. ¿Hay una mejor manera de hacerlo sin repetir el patrón?

+1

¿Qué sabor de expresión regular se utiliza? .Net permite este tipo de "coincidencia de paréntesis", pero otros sabores no lo hacen. – cristobalito

+0

Una exploración relacionada: http://stackoverflow.com/questions/3165755/capturing-thispartonly-and-thispartonly-with-the-same-group – polygenelubricants

Respuesta

17

Usted puede obtener una solución sin repetir, haciendo uso de backreferences y conditionals:

/^(")?(pattern)(?(1)\1|)$/ 

Partidos:

  • patrón
  • "patrón"

NO partido:

  • "patrón
  • patrón"

Este patrón es algo complejo, sin embargo. Primero busca una cotización opcional y la pone en referencia inversa 1 si se encuentra una. Luego busca tu patrón. Luego utiliza la sintaxis condicional para decir "si se encuentra nuevamente la referencia inversa 1, haga coincidirla, de lo contrario no concuerde con nada". El patrón completo es anchored (lo que significa que debe aparecer solo en una línea) para que las comillas no coincidentes no se capturen (de lo contrario, el pattern en pattern" coincidiría).

Tenga en cuenta que la compatibilidad con condicionales varía según el motor y las expresiones más detalladas pero repetitivas serán más ampliamente compatibles (y probablemente más fáciles de entender).


Actualización: Una versión mucho más simple de esta expresión regular sería /^(")?(pattern)\1$/, que no necesita un condicional. Cuando estaba probando esto inicialmente, el probador que estaba usando me dio un falso negativo, lo que me llevó a descontarlo (¡Uy!).

Dejaré la solución con la condición de posteridad e interés, pero esta es una versión más simple que es más probable que funcione en una amplia variedad de motores (las referencias son la única característica que se usa aquí y que podrían no ser compatibles)

+0

Aaarrg, recién comencé a buscar la sintaxis condicional de regex-if en el libro de Friedel . Fuiste más rápido +1 (el siguiente +1 es para el patrón recursivo ;-) –

+0

@rubber Érase una vez que sabía cómo hacer expresiones recursivas recursivas, pero creo que me olvidé por el bien de la humanidad;) –

+0

@Daniel: La humanidad probablemente no le importaría si te olvidas de condicionales, también. '^ ("?) pattern \ 1 $ 'funciona bien. (La respuesta eliminada de @Wuputah no funcionó porque no estaba anclada. Y @Tim, los cuantificadores posesivos/grupos atómicos no son necesarios.) –

0

Dependiendo del idioma que esté utilizando, debería poder utilizar las referencias retrospectivas. Algo como esto, por ejemplo:

(["'])(pattern)\1|^(pattern)$ 

De esta manera, usted está requiriendo que, o bien no hay cotizaciones, o que el presupuesto mismo es usado en ambos extremos.

0

Esto debería funcionar con recgex regex (que necesita más tiempo para hacerlo bien). Mientras tanto: en Perl, puede compilar regex auto modificante.Voy a dejar esto como un ejemplo académico ;-)

my @stuff = ('"pattern"', 'pattern', 'pattern"', '"pattern' ); 

foreach (@stuff) { 
    print "$_ OK\n" if /^ 
         (")? 
         \w+ 
         (??{defined $1 ? '"' : ''}) 
         $ 
         /x 
} 

Resultado:

"pattern" OK 
pattern OK 
Cuestiones relacionadas