2011-05-10 36 views
13

estoy haciendo una expresión regular de fecha coincidente, y que todo va bastante bien, tengo esto hasta ahora:PHP expresiones regulares grupo no captura no coincidencia

"/(?:[0-3])?[0-9]-(?:[0-1])?[0-9]-(?:20)[0-1][0-9]/" 

Será (con suerte) que coincida sola o días y meses de dos dígitos, y años dígitos dobles o cuádruples en el siglo XXI. Algunas pruebas y errores me han llevado hasta aquí.

Pero, Tengo dos preguntas simples con respecto a estos resultados:

  1. (?:) lo que es una simple explicación para esto? Aparentemente es un grupo que no combina. Pero luego ...

  2. ¿Para qué está el ?? p.ej. (?)?

Respuesta

25

[Edited (de nuevo) para mejorar el formato y fijar la introducción.]

Este es un comentario y una respuesta.

La parte de respuesta ... Estoy de acuerdo con la respuesta anterior de alex.

  1. (?:), en contraste con (), se utiliza para evitar la captura del texto, en general, a fin de tener menos referencias volver tirado con los que quiere o para mejorar el rendimiento de velocidad.

  2. ¿Cuál? siguiendo el (?:) - o cuando se sigue algo excepto * + ? o {} - significa que el elemento anterior puede o no encontrarse dentro de una coincidencia legítima. Por ejemplo, /z34?/ coincidirá Z3, así como z34 pero no coincidirá con z35 o Z etc.

La parte comentario ... Hice lo que podría ser considerado como la mejora de la expresión regular que estaba trabajando:

(?:^|\s)(0?[1-9]|[1-2][0-9]|30|31)-(0?[1-9]|10|11|12)-((?:20)?[0-9][0-9])(?:\s|$) 

- En primer lugar, evita cosas como 0-0-2011

- En segundo lugar, evita cosas como 233443-4-201154564

- En tercer lugar, que incluye cosas como 1 -1-202 2

- Forth, que incluye cosas como 1-1-11

- En quinto lugar, evita cosas como 34-4-11

- En sexto lugar, le permite capturar el día , mes y año para que pueda consultar estos más fácilmente en el código.código que, por ejemplo, haría una verificación adicional (es el segundo grupo capturado 2 y es el primer grupo capturado 29 y este es un año bisiesto o el primer grupo capturado es < 29) para ver si una fecha de feb 29 calificado o no.

Finalmente, tenga en cuenta que todavía obtendrá fechas que no existirán, por ejemplo, 31-6-11. Si se quiere evitar estos, a continuación, tratar:

(?:^|\s)(?:(?:(0?[1-9]|[1-2][0-9]|30|31)-(0?[13578]|10|12))|(?:(0?[1-9]|[1-2][0-9]|30)-(0?[469]|11))|(?:(0?[1-9]|[1-2][0-9])-(0?2)))-((?:20)?[0-9][0-9])(?:\s|$) 

Además, asumí las fechas serían precedidos y seguidos por un espacio (o pedir/final de la línea), pero es posible que desee ot ajustar eso (por ejemplo, para permitir las puntuaciones).

Un comentarista hace referencia en otro lugar de este recurso que le puede resultar útil: http://rubular.com/

+0

Genial, muy completo y útil en la primera parte. Actualmente estoy usando '/ [0-3]? [0-9] - [0-1]? [0-9] - (?: 20)? [0-1] [0-9] /' entonces ejecutando un 'checkdate()' en los componentes para encargarse de las fechas falsas. – Ben

6
  1. Es un grupo no de captura. No puede retroceder referenciarlo. Generalmente se usa para declinar las referencias y/o aumentar el rendimiento.
  2. Significa que el grupo de captura anterior es opcional.
+0

Groovy. Para los futuros usuarios, aquí hay una explicación adicional semi-útil: http://www.regular-expressions.info/named.html – Ben

3

sub-patrones

sub-patrones están delimitadas por paréntesis (entre paréntesis), que se pueden anidar. Marcar parte de un patrón como un subpatrón hace dos cosas:

  1. Localiza un conjunto de alternativas. Por ejemplo, el patrón cat (aract | erpillar |) coincide con una de las palabras "cat", "cataract" o "oruga". Sin los paréntesis, coincidiría con "catarata", "erpillar" o la cadena vacía.
  2. Configura el subpatrón como un subconjunto de captura (como se define en arriba). Cuando todo el patrón coincide, la porción del sujeto cadena que coincide con el subpatrón se devuelve a la persona que llama a través de el argumento ovector de pcre_exec(). Los paréntesis de apertura se cuentan de izquierda a derecha (comenzando desde 1) para obtener los números de los subpatrones de captura .

Por ejemplo, si la cadena "the red king" se compara con el patrón the ((red | white) (king | queen)) las subcadenas capturadas son "red king", "red" y " rey ", y están numerados 1, 2 y 3.

El hecho de que los paréntesis simples cumplan dos funciones no siempre es útil. A menudo, se requiere un subconjunto de agrupación sin un requisito de captura. Si un paréntesis de apertura va seguido de "?:", El subpatrón no realiza ninguna captura, y no se cuenta cuando se calcula el número de subpatrones de captura subsiguientes. Por ejemplo, si la cadena "la reina blanca" se compara con el patrón el ((?: Rojo | blanco) (rey | reina)) las subcadenas capturadas son "reina blanca" y "reina", y están numeradas 1 y 2 La cantidad máxima de subcadenas capturadas es 65535. Sin embargo, tal vez no sea posible compilar tales patrones grandes, dependiendo de las opciones de configuración de libpcre.

Como una abreviatura conveniente, si se requiere alguna configuración de opción al inicio de un subpatrón que no captura, las letras de opción pueden aparecer entre el "?" y el ":". Por lo tanto, los dos patrones

(?i:saturday|sunday) 
(?:(?i)saturday|sunday) 

coinciden exactamente con el mismo conjunto de cadenas. Como las ramas alternativas se prueban de izquierda a derecha y las opciones no se restablecen hasta que se alcanza el final del subpatrón, la configuración de una opción en una rama afecta a las ramas posteriores, por lo que los patrones anteriores coinciden con "DOMINGO" y "Sábado".

Es posible nombrar un subpatrón utilizando la sintaxis (? Ppattern). Este subpatrón se indexará en la matriz de coincidencias por su posición numérica normal y también por su nombre. PHP 5.2.2 introdujo dos sintaxis alternativas (? Patrón) y (? 'Name'pattern).

A veces es necesario tener múltiples subgrupos coincidentes, pero alternando en una expresión regular. Normalmente, a cada uno de ellos se les daría su propio número de referencia inversa, aunque solo uno de ellos podría coincidir. ?. Para superar esto, el (| sintaxis permite tener números duplicados Considere las siguientes expresiones regulares coincidentes con la cadena Domingo:

(?:(Sat)ur|(Sun))day 

aquí Sun se almacena en referencia inversa 2, mientras que retrorreferencia 1 está vacía Matching produce sábado en referencia inversa. . 1, mientras que retrorreferencia 2 no existe Cambiar el patrón de usar los (| corrige este problema:?

(?|(Sat)ur|(Sun))day 

Usando este modelo, tanto Sun y Sat serían almacenados en referencia inversa 1.

Referencia: http://php.net/manual/en/regexp.reference.subpatterns.php

Cuestiones relacionadas