2011-09-22 12 views
11

Ejemplo:¿El cuantificador {0} tiene sentido en algunos escenarios?

/(?: Foo) {0} bar/

vi algo como esto en otra respuesta. Al principio pensé "¿qué debería ser eso?", Pero luego, "OK podría tener sentido, una especie de aspecto negativo detrás", por lo que Foo no está permitido antes de bar, pero esto no está funcionando.

se puede ver este here on Regexr: Se coincide sólo con bar pero también coincide con el bar en Foobar.
cuando agrego un ancla para el inicio de la fila:

/^(?:Foo){0}bar/ 

se comporta como espero. Solo coincide con bar y no con bar en Foobar.

Pero eso es exactamente el mismo comportamiento que si solo usara /bar/ o /^bar/.

¿Es el cuantificador {0} solo un efecto secundario inútil, o hay realmente un comportamiento útil para eso?

Respuesta

11

Hay buenos usos de {0}. Le permite a definir grupos que no tiene la intención de capturar en el momento. Esto puede ser útil en algunos casos:

  • El mejor - uso del grupo en expresiones regulares recursivas (u otras construcciones extrañas). Perl, por ejemplo, tiene (?(DEFINE)) para el mismo uso.
    Un ejemplo rápido - en PHP, esto coincidirá barFoo (working example):

    preg_match("/(?:(Foo)){0}bar(?1)/", "barFoo", $matches); 
    
  • Adición de un grupo capturado fallado (llamado o numerada) a los Resultados de los partidos.

  • manteniendo intactos los índices de todos los grupos en caso de que se refactorice el patrón.

Menos buenos usos, como Peter sugirió son útiles en:

  • patrones generados.
  • Legibilidad: Patrones con cierta duplicación, donde {0} y {1} pueden llevar a pensar en la dirección correcta. (OK, no es el mejor punto)

Todos estos son casos raros, y en la mayoría de los patrones es un error.

+0

Eso es increíble, Kobi. Esto solo es útil en un motor que tiene subrutinas pero no '(? (DEFINE))', creo que solo es Ruby y probablemente Python con el módulo 'regex'. Probado en Ruby: '(? :(Foo)) {0} bar \ g <1>' +1000! – zx81

+1

En caso de que alguien esté interesado, no está trabajando en Python con el módulo 'regex'. Pero se le ocurrió esta alternativa, que funciona: '(? :(Foo) $ ^)? Bar (? 1)' – zx81

2

En expresiones regulares tradicionales, /x{0}/ (language = {x n: x = 0}) significaría "partido exactamente 0 de x", que es el mismo que // (language = {Λ}). Como los dos son equivalentes, debería poder eliminar cualquier /x{0}/ que encuentre por ahí.

Pero las PCRE y otras extensiones de expresiones regulares pueden volverse bastante bizantinas. No me sorprendería si /x{0}/ hiciera algo en Perl. Estaría disgustado, pero no sorprendido.

Creo que es probablemente un artefacto de un programa que genera automáticamente expresiones regulares pero no las simplifica. Lo cual es una pena, ya que es muy fácil escribir programas que simplifiquen las expresiones regulares.

+0

_ "Estaría disgustado, pero no me sorprende." _ :) –

+0

¿Es realmente tan fácil escribir programas que simplifican las expresiones regulares? Eso suena interesante ... – Kobi

3

Un recuento de repeticiones explícito de cero puede ser útil en expresiones regulares generadas automáticamente. Evita codificar un caso especial para cero repeticiones de esta manera.

2

No puedo pensar en una sola buena razón para usar x{0}. Pero puedo pensar en varios por qué debe evitarse:

  • Es inútil ya que siempre coincide.
  • Disminuye la velocidad del motor regex (a menos que la regex esté precompilada).
  • Es probable que sea un signo de malentendido por parte del autor de la expresión regular.

estoy dispuesto a apostar que alguien que escribe (?:foo){0} es tratando de decir "asegurarse de que foo no coincide aquí", que por supuesto falla porque la cadena vacía siempre se puede adaptar, si foo está allí o no. Para eso son las aserciones negativas. (?<!foo)bar etc.

Cuestiones relacionadas