2010-10-13 26 views
107

Tengo una lista de cadenas. Algunos de ellos son de la forma 123-...456. La parte variable "..." puede ser:¿Cómo hacer coincidir, pero no capturar, parte de una expresión regular?

  • la cadena "apple" seguida de un guion, p. 123-apple-456
  • la cadena "banana" seguida de un guion, p. Ej. 123-banana-456
  • una cadena en blanco, p. 123-456 (tenga en cuenta que hay un solo guión)

Cualquier palabra que no sea "apple" o "banana" no es válida.

Para estos tres casos, me gustaría hacer coincidir "manzana", "banana" y "", respectivamente. Tenga en cuenta que nunca quiero capturar el guión, pero siempre quiero coincidir con. Si la cadena no tiene el formato 123-...456 como se describe arriba, entonces no hay ninguna coincidencia.

¿Cómo escribo una expresión regular para hacer esto? Supongamos que tengo un sabor que permite mirar hacia adelante, mirar hacia atrás, mirar hacia afuera y grupos que no capturan.


La observación clave aquí es que cuando se tiene ya sea "manzana" o "banana", que también debe tener el guión final, pero que no desea para que coincidan. Y cuando está haciendo coincidir la cadena en blanco, no debe tener el guión final. Una expresión regular que encapsula esta afirmación será la correcta, creo.

+0

Depende del sabor de la expresión regular. ¿Qué lenguaje de programación y/o sabor regex estás usando? – BoltClock

+0

@BoltClock: Agregué algunas aclaraciones. Gracias por la respuesta. –

+0

¿Desea hacer coincidir todo excepto los guiones? – BrunoLM

Respuesta

1

Prueba esto:

/\d{3}-(?:(apple|banana)-)?\d{3}/ 
+1

Esto no es correcto ya que coincide, por ejemplo, con "123-coco-456". –

+0

@david: ¿cómo es eso diferente de tu ejemplo "banana"? – SilentGhost

+0

@SilentGhost: I * solo * desea capturar 'apple' o' banana' o "". Todos los otros valores son inválidos, como dije. –

7

Probar:

123-(?:(apple|banana|)-|)456 

que coincidirá apple, banana, o una cadena en blanco, y después de que habrá un 0 o 1 guiones. Estaba equivocado acerca de no tener la necesidad de un grupo de captura. Tonto de mí.

+0

Esto no es correcto ya que coincide, por ejemplo, con "123-coco-456". –

+0

Pensé que lo querías más en general ... arreglado. – Thomas

+1

esto coincidirá con '' 123--456 '' – SilentGhost

105

La única manera de no capturar algo está utilizando look-around assertions:

(?<=123-)((apple|banana)(?=-456)|(?=456)) 

Debido non-capturing groups (?:…) incluso con toda la expresión regular capta su contenido emparejados. Pero esta expresión regular solo coincide con apple o banana si está precedida por 123- y seguida por -456, o coincide con la cadena vacía si está precedida por 123- y luego por 456.

+1

+1 - En este caso, puede solucionarlo utilizando el grupo 1 en lugar del grupo 0, pero esta es una distinción excelente (¡y sutil!). –

+0

@Ben En blanco: Definitivamente depende de cómo se interpretan "coincidencia" y "captura". – Gumbo

+5

No es compatible con JavaScript, * yay *! sería bueno tener un método amigable JS, pero no está nada mal, +0.5 (redondeando; D) – GiantCowFilms

9

Actualización: ¡Gracias a Germán Rodríguez Herrera!

en TRY javascript: /123-(apple(?=-)|banana(?=-)|(?!-))-?456/

Recuerde que el resultado está en el grupo 1

Regular expression visualization

Debuggex Demo

-2

Con mucho, la más simple (que funciona para Python) es '123-(apple|banana)-?456'.

+0

Esto coincidiría con '123-apple456', por lo que no es correcto. – Loren

1

he modificado una de las respuestas (por @ op1ekun):

123-(apple(?=-)|banana(?=-)|(?!-))-?456 

La razón es que la respuesta de @ op1ekun también coincide con "123-apple456", sin el guión después de la manzana.

Cuestiones relacionadas