Expresiones regulares que funcionan “en cualquier lugar”
(johndcook.com)- Las expresiones regulares tienen funciones y sintaxis distintas según la implementación, por lo que un patrón que funcionaba en una herramienta puede fallar o requerir modificaciones en otro entorno
- Mientras más acostumbrado estés a entornos con muchas funciones, como Perl, más seguido te toparás con problemas de compatibilidad; y si además consideras computadoras donde no tienes permiso para instalar software, es más seguro usar un subconjunto común
- Si se define “en cualquier lugar” de la forma más estricta, el alcance se reduce tanto que prácticamente solo quedan literales, clases de caracteres
[…]y caracteres especiales básicos como. * ^ $ - Si usas GNU
sed,awk,grepjunto con la opción-Eensedygrep, se amplía el conjunto común de funciones disponibles, pero en esta combinaciónawksuele ser el mínimo común denominador - Emacs requiere barras invertidas para
+? ( ) { } |y el significado de\s,\Stambién es distinto, así que para usar la misma expresión regular en varias herramientas hay que revisar incluso las sintaxis excepcionales
Por qué es difícil la compatibilidad de las expresiones regulares
- La mayor incomodidad de las expresiones regulares proviene de las diferencias entre implementaciones
- Una función disponible en una herramienta puede no existir en otra
- Incluso la misma función puede tener una sintaxis ligeramente distinta
- Perl es un entorno de expresiones regulares con muchas funciones, así que algo que parece obvio tomando Perl como referencia puede faltar en otros entornos
- También se pueden usar reemplazos similares a Perl para otras herramientas, pero no son estándar, lo que dificulta enviar a colegas o clientes código que puedan ejecutar de inmediato
- Si además se consideran situaciones en las que hay que trabajar en computadoras donde no se puede instalar software, hace falta un enfoque que busque un subconjunto de funciones de expresiones regulares que funcione en varios entornos
- Mientras más estricta sea la definición de “en cualquier lugar”, menos funciones se pueden usar
- Literales
- Clases de caracteres
[…] - Caracteres especiales
. * ^ $
Alcance común en sed, awk, grep y Emacs
- Si se limita el conjunto de herramientas objetivo a
sed,awk,grepy Emacs, el criterio de “en cualquier lugar” puede relajarse un poco - Al usar las versiones GNU de
sed,awk,grepy aplicar la opción-Easedygrep, la lista de funciones comunes se amplía- Las funciones de expresiones regulares de las tres herramientas son parecidas
- Las funciones de
awktambién suelen estar disponibles en las otras herramientas - Como excepción, los límites de palabra en
awkusan\<,\>, y son distintos de\b,\B
- Emacs corresponde a la mayoría de las funciones de
awk, pero tiene diferencias de sintaxis- Para que
+ ? ( ) { } |cumplan el mismo rol que enawk, necesitan una barra invertida antes - Las expresiones equivalentes a
\s,\Sdeawken Emacs son\s-,\S-
- Para que
- En Emacs,
\s,\Sno significan espacio/no espacio, sino que inician una clase de caracteres- La clase
-significa espacio \s.es un carácter de puntuación\S.es un carácter que no es de puntuación
- La clase
- Con este criterio, las funciones que se pueden usar son las siguientes
.^,$[…],[^…]*\w,\W,\s,\S- Referencias inversas de
\1a\9 \b,\B?,+- Alternativas con
| - Repetición
{n,m} - Captura
(...)
- Sin embargo,
gawkadmite referencias inversas en las cadenas de reemplazo, pero no en la expresión regular en sí look-aroundpuede considerarse una función avanzada, y\dpuede parecer una función básica para dígitos, pero muchas variantes de expresiones regulares no lo admiten
1 comentarios
Opiniones en Hacker News
En Emacs se sufre especialmente porque casi se siente como adivinar qué hay que escapar
Existe una alternativa llamada
rx[0], pero en la práctica no es agradable de usarMás allá de la sintaxis de las expresiones regulares en sí, en la etapa de uso real también aparecen a menudo problemas de codificación y escape
Si ingresas una expresión regular en el shell, tienes que escaparla correctamente; en Python, debes asegurarte de que sea una cadena raw, y así
Aun así, que la forma de usar expresiones regulares en la mayoría de las herramientas haya convergido dentro de un rango más o menos parecido es casi un milagro moderno
[0]: https://www.gnu.org/software/emacs/manual/html_node/elisp/Rx...
Siguen apareciendo situaciones en las que se superponen reglas de escape distintas
(y)coincidan literalmente resulta un poco cómodoEl autor parece estar a punto de decirlo, sin terminar de llegar: al final, las expresiones regulares básicas de POSIX funcionan en todas partes
Aunque con la salvedad de que no todos se han puesto al día con la edición 8 de Single Unix Specification, y que en esa edición las BRE cambiaron un poco
Si no hubiera existido esa salvedad, para empezar no habría hecho falta escribir ese artículo
Hace tiempo escribí un paper sobre encontrar expresiones regulares que hagan match de la misma manera tanto bajo semántica codiciosa como bajo semántica leftmost maximal
https://par.nsf.gov/servlets/purl/10534654
Siempre he sido exigente con dejar claro qué lenguaje de expresiones regulares acepta cada herramienta, y qué es lo que hace match: cualquier subcadena, prefijo, sufijo, la cadena completa, una línea o una subcadena dentro de una línea
Aquí están [los más usados][1], y además están PCRE y Python
Me tomó un tiempo aprender que algunos de los formatos antiguos que se ven en lugares como grep [están especificados en POSIX][2]
[1]: https://cppreference.com/cpp/regex#Regular_expression_gramma...
[2]: https://pubs.opengroup.org/onlinepubs/009696899/basedefs/xbd...
Quiero compartir la página de Russ Cox sobre expresiones regulares
Me parece un buen recurso para leer
https://swtch.com/~rsc/regexp/
Por razones como estas es importante RFC 9485, I-Regexp: An Interoperable Regular Expression Format
https://datatracker.ietf.org/doc/html/rfc9485
El paquete regexp de la biblioteca estándar de Go usa el motor RE2, por eso no admite referencias inversas
Se pueden usar en sustituciones, pero no en matching
regexpno usa re2; es una implementación separada de los mismos conceptosDespués de sufrir frustraciones similares con motores de reglas, motores de plantillas y motores tipo IFTTT, hice una biblioteca en Rust para JSONLogic y también uso bindings para otros lenguajes
https://github.com/GoPlasmatic/datalogic-rs
La documentación de JSON Schema también incluye un subconjunto recomendado de expresiones regulares
https://json-schema.org/understanding-json-schema/reference/...