Alternativas de afirmación de detrás de la expresión variable para expresiones regulares

¿Existe una implementación de expresiones regulares en Python / PHP / JavaScript que admita una longitud variable detrás de la aserción?

/(?<!foo.*)bar/ 

¿Cómo puedo escribir una expresión regular que tenga el mismo significado, pero que no use ninguna de las siguientes afirmaciones?

¿Existe la posibilidad de que este tipo de afirmación se implementará algún día?

Las cosas están mucho mejor de lo que pensaba.

Actualizar:

(1) Ya hay implementaciones de expresiones regulares que soportan la aserción de búsqueda y seguimiento de longitud variable.

El módulo de expresiones regulares de Python (no es el estándar, pero el módulo de regex adicional) admite tales aserciones (y tiene muchas otras características interesantes).

 >>> import regex >>> m = regex.search('(?>> print m.group() bar >>> m = regex.search('(?>> print m None 

Fue una gran sorpresa para mí que hay algo en las expresiones regulares que Perl no puede hacer y Python puede. Probablemente, ¿hay implementación de “expresión regular mejorada” para Perl también?

(Gracias y +1 a MRAB).

(2) Hay una característica genial \K en expresiones regulares modernas.

Estos símbolos significan que cuando realiza una sustitución (y desde mi punto de vista, el caso de uso más interesante de las aserciones es la sustitución), todos los caracteres que se encontraron antes de \K no deben cambiarse.

 s/unchanged-part\Kchanged-part/new-part/x 

Eso es casi como una aserción retrospectiva, pero no tan flexible, por supuesto.

Más sobre \K :

  • Perl Expresión Regular \ K Truco
  • PCRE Regex Spotlight: \ K

Según tengo entendido, no se puede usar \ K dos veces en la misma expresión regular. Y no puedes decir hasta qué punto quieres “matar” a los personajes que has encontrado. Eso es siempre hasta el principio de la línea.

(Gracias y +1 a ikegami).

Mis preguntas adicionales:

  • ¿Es posible decir qué punto debe ser el punto final del efecto \K ?
  • ¿Qué pasa con las implementaciones de expresiones regulares mejoradas para Perl / Ruby / JavaScript / PHP? Algo como regex para Python.

La mayoría de las veces, puede evitar las miradas de longitud variable utilizando \K

 s/(?<=foo.*)bar/moo/s; 

sería

 s/foo.*\Kbar/moo/s; 

Las miradas negativas son un poco más complicadas.

 s/(? 

sería

 s/^(?:(?!foo).)*\Kbar/moo/s; 

porque (?:(?!STRING).)* es STRING como [^CHAR]* es CHAR .


Si solo estás haciendo coincidencias, es posible que ni siquiera necesites el \K

 /foo.*bar/s /^(?:(?!foo).)*bar/s 

Para Python hay una implementación de expresiones regulares que soporta la apariencia de longitud variable detrás de:

http://pypi.python.org/pypi/regex

Está diseñado para ser compatible con el módulo de re estándar.

Puedes invertir la cadena Y el patrón y usar lookahead de longitud variable

(rab(?!\w*oof)\w*)

coincidencias en negrita:

raboof rab7790oof raboo rabof rab rabo raboooof rabo

Solución original que yo sepa por:

Jeff ‘japhy’ Pinyan

La expresión regular que muestre encontrará cualquier instancia de bar que no esté precedida por foo .

Una alternativa simple sería primero hacer coincidir foo con la cadena y encontrar el índice de la primera aparición. Luego busque la bar , y vea si puede encontrar una ocurrencia que venga antes de ese índice.

Si quieres encontrar instancias de bar que no estén precedidas directamente por foo , también podría proporcionar una expresión regular para eso (sin usar lookbehind), pero será muy feo. Básicamente, invierta el sentido de /foo/ – es decir /[^f]oo|[^o]o|[^o]|$/ .

 foo.*|(bar) 

Si foo está en la cadena primero, entonces la expresión regular coincidirá, pero no habrá grupos.

De lo contrario, encontrará la bar y la asignará a un grupo.

Por lo tanto, puede usar esta expresión regular y buscar sus resultados en los grupos encontrados:

 >>> import re >>> m = re.search('foo.*|(bar)', 'f00bar') >>> if m: print(m.group(1)) bar >>> m = re.search('foo.*|(bar)', 'foobar') >>> if m: print(m.group(1)) None >>> m = re.search('foo.*|(bar)', 'fobas') >>> if m: print(m.group(1)) >>> 

Fuente.