Conoce tus sabores regex
Hay una cantidad sorprendente de personas que piensan que las expresiones regulares son esencialmente agnósticas al lenguaje. Sin embargo, en realidad hay diferencias bastante sustanciales entre los sabores, y especialmente para el golf de código es bueno conocer algunos de ellos y sus características interesantes, para que pueda elegir el mejor para cada tarea. Aquí hay una descripción general de varios sabores importantes y lo que los distingue de los demás. (Esta lista no puede estar realmente completa, pero avíseme si me perdí algo realmente deslumbrante).
Perl y PCRE
Los estoy tirando en una sola olla, ya que no estoy demasiado familiarizado con el sabor de Perl y son en su mayoría equivalentes (PCRE es para expresiones regulares compatibles con Perl después de todo). La principal ventaja del sabor Perl es que en realidad se puede llamar al código Perl desde el interior de la expresión regular y la sustitución.
- Recursión / subrutinas . Probablemente la característica más importante para el golf (que solo existe en un par de sabores).
- Patrones condicionales
(?(group)yes|no)
.
- Apoya el cambio de caso en la cadena de reemplazo con
\l
, \u
, \L
y \U
.
- PCRE permite alternar en retrospectivas, donde cada alternativa puede tener una longitud diferente (pero fija). (La mayoría de los sabores, incluido Perl, requieren mirar hacia atrás para tener una longitud fija total).
\G
para anclar una partida al final de la partida anterior.
\K
para reiniciar el comienzo del partido
- PCRE admite propiedades de caracteres Unicode y scripts .
\Q...\E
para escapar de series más largas de personajes. Es útil cuando intenta hacer coincidir una cadena que contiene muchos metacaracteres.
.RED
Este es probablemente el sabor más poderoso, con muy pocas deficiencias.
Una deficiencia importante en términos de golf es que no admite cuantificadores posesivos como algunos otros sabores. En lugar de .?+
tendrás que escribir (?>.?)
.
Java
- Debido a un error (consulte el Apéndice), Java admite un tipo limitado de mirar hacia atrás de longitud variable: puede mirar hacia atrás hasta el comienzo de la cadena
.*
desde donde ahora puede comenzar una búsqueda hacia adelante, como (?<=(?=lookahead).*)
.
- Soporta unión e intersección de clases de caracteres.
- Tiene el soporte más extenso para Unicode, con clases de caracteres para "scripts, bloques, categorías y propiedades binarias Unicode" .
\Q...\E
como en Perl / PCRE.
Rubí
En versiones recientes, este sabor es igualmente poderoso que PCRE, incluido el soporte para llamadas de subrutina. Al igual que Java, también admite la unión e intersección de clases de caracteres. Una característica especial es la clase de caracteres incorporada para dígitos hexadecimales: \h
(y el negado \H
).
Sin embargo, la característica más útil para el golf es cómo Ruby maneja los cuantificadores. En particular, es posible anidar cuantificadores sin paréntesis. .{5,7}+
funciona y también lo hace .{3}?
. Además, a diferencia de la mayoría de los otros sabores, si 0
se puede omitir el límite inferior de un cuantificador , por ejemplo, .{,5}
es equivalente a .{0,5}
.
En cuanto a las subrutinas, la principal diferencia entre las subrutinas de PCRE y las subrutinas de Ruby es que la sintaxis de Ruby es un byte más larga (?n)
vs \g<n>
, pero las subrutinas de Ruby se pueden usar para capturar, mientras que PCRE restablece las capturas después de que finaliza una subrutina.
Finalmente, Ruby tiene una semántica diferente para los modificadores relacionados con la línea que la mayoría de los otros sabores. El modificador que generalmente se llama m
en otros sabores siempre está activado en Ruby. Así ^
, y $
siempre que coincida con el comienzo y el final de una línea no sólo el principio y el final de la cadena. Esto puede ahorrarle un byte si necesita este comportamiento, pero le costará bytes adicionales si no lo hace, ya que tendrá que reemplazar ^
y $
con \A
y \z
, respectivamente. Además de eso, el modificador que generalmente se llama s
(que hace que los .
avances de línea coincidan) se llama m
en Ruby. Esto no afecta el recuento de bytes, pero debe tenerse en cuenta para evitar confusiones.
Pitón
Python tiene un sabor sólido, pero no conozco ninguna característica particularmente útil que no encontrarías en ningún otro lado.
Sin embargo , hay un sabor alternativo que está destinado a reemplazar el re
módulo en algún momento y que contiene muchas características interesantes. Además de agregar compatibilidad para operadores de combinación de recursión, lookbehinds de longitud variable y clase de caracteres, también tiene la característica única de coincidencia difusa . En esencia, puede especificar una serie de errores (inserciones, eliminaciones, sustituciones) que están permitidos, y el motor también le dará coincidencias aproximadas.
ECMAScript
El sabor ECMAScript es muy limitado y, por lo tanto, rara vez es muy útil para el golf. Lo único que tiene que hacer es que la clase de caracteres vacía negada [^]
coincida con cualquier carácter, así como la clase de caracteres vacía que falla incondicionalmente []
(a diferencia de lo habitual (?!)
). Desafortunadamente, el sabor no tiene ninguna característica que lo haga útil para problemas normales.
Lua
Lua tiene su propio sabor bastante único, que es bastante limitado (por ejemplo, ni siquiera puede cuantificar grupos) pero viene con un puñado de características útiles e interesantes.
- Tiene una gran cantidad de shorthands para las clases de caracteres incorporadas, incluidos los signos de puntuación, mayúsculas y minúsculas y dígitos hexadecimales.
- Con
%b
él admite una sintaxis muy compacta para que coincida con cadenas equilibradas. Por ejemplo, %b()
coincide con ay (
luego todo hasta una coincidencia )
(omitiendo correctamente los pares coincidentes internos). (
y )
pueden ser dos caracteres cualquiera aquí.
Aumentar
El sabor regex de Boost es esencialmente el de Perl. Sin embargo, tiene algunas características nuevas y agradables para la sustitución de expresiones regulares, que incluyen cambios de casos y condicionales . Este último es exclusivo de Boost, que yo sepa.