Lo mínimo que todo programador debería saber sobre expresiones regulares

Este post es una traducción de un excelente artículo de Mike Malone, “The Absolute Bare Minimum Every Programmer Should Know About Regular Expressions“.

¿Qué diablos es una expresión regular?

Las expresiones regulares son cadenas de texto que se han formateado según una notación que permite describir y analizar un texto. Muchos programadores (incluso algunos de los buenos) consideran las expresiones regulares un estorbo, y es una lástima porque vienen bien muy a menudo. Una vez que has conseguido dominarlas, puedes usar las expresiones regulares para resolver incontables problemas del mundo real.

Las expresiones regulares funcionan de forma muy parecida a los “comodines” en los nombre de archivo que, en Windows o *nix, te permiten especificar varios archivos usando caracteres especiales como * o ? (oops, ¿he usado un comodín mientras definía un comodín?). Pero en las expresiones regulares los caracteres especiales o metacaracteres son mucho más expresivos.

Como los comodines, las expresiones regulares tratan la mayoría de los caracteres como texto literal. La expresión regular mike, por ejemplo, sólo se correspondera con las letras m - i - k - e, en ese orden. Pero las expresiones regulares proporcionan un extenso conjunto de metacaracteres que hacen que el uso de simples comodines parezca totalmente primitivo.

Conoce los metacaracteres: ^[](){}.*?\|+$ y a veces -

Ya sé, parece que intimidan, pero son caracteres realmente bonitos una vez que los conoces.

Las Anclas de Línea: ‘^’ y ‘$’

Los metacaracteres ‘^’ (acento circunflejo) y ‘$’ (dolar) representan el principio y el final de una línea de texto, respectivamente. Como he mencionado antes, la expresión regular mike se corresponderá con las letras m - i - k - e, pero lo hará en cualquier parte de una línea (p. ej. se correspondería con “yo soy mike” o incluso con “carmike”). El carácter ‘^’ se usa para anclar la correspondencia al principio de la línea, así ^mike sólo encontraría líneas que comenzaran por “mike”. De forma similar, la expresión mike$ sólo encontraría m - i - k - e al final de una línea (pero aún se correspondería con “carmike”).

Si combinamos los dos caracteres de anclaje de línea podemos buscar líneas de texto que contengan una secuencia de caracteres específica. La expresión ^mike$ sólo se corresponderá con la palabra “mike” que esté sola en una línea - nada más y nada menos. De forma similar, la expresión ^$ es útil para encontrar líneas en blanco, donde el principio de la línea está seguido por el final.

La Clase de Carácter: ‘[]’

Los corchetes cerrados, conocidos como clase de carácter, te permiten hacer una correspondencia con cualquiera de varios caracteres. Supón que quieres encontrar la palabra “gray”, pero también quieres encontrar la variante “grey”. Una clase de carácter te permitirá que encuentres ambas. La expresión regular gr[ea]y se interpreta como “g, seguido de r, seguido de e ó a, seguido de y”.

Si usas [^ ... ] en lugar de [ ... ], la clase se corresponde con cualquier carácter que no esté listado. El ^ precedente “niega” la lista. En lugar de listar todos los caracteres que quieres incluir en la clase, puedes listar los caracteres que no quieres incluir. Observa que el carácter ^ en este caso tiene un significado diferente cuando se usa fuera de los corchetes, usándose entonces para especificar el principio de una línea.

El Metacarácter de Clase de Carácter: ‘-’

En el ámbito de una clase de carácter, el metacarácter de clase de carácter ‘-’ (guión) indica un rango de caracteres. En lugar de [01234567890abcdefABCDEF] podemos escribir [0-9a-fA-F]. Qué cómodo. El guión es un metacarácter sólo cuando está dentro de corchetes; en cualquier otro caso sólo representa un guión normal.

Pero espera, hay una excepción. Si un guión es el primer carácter de una clase de carácter, no se considera un metacarácter (no puede representar un rango, ya que un rango necesita un principio y un final), sino que se corresponde con un guión normal. De forma similar, la interrogación y el punto se suelen usar como metacaracteres, pero no cuando están en el interior de una clase (en la clase [-0-9.?] el único carácter especial es el guión entre el 0 y el 9).

Encontrar Cualquier Carácter con un Punto: ‘.’

El metacarácter ‘.’ (punto) es un atajo para una clase de carácter que se corresponda con cualquier carácter. Es muy cómodo cuando quieres encontrar cualquier carácter en una posición concreta en una cadena. Una vez más, el metacarácter punto no es un metacarácter cuando está dentro de una clase de carácter. ¿Empiezas a ver un patrón? La lista de metacaracteres es diferente dentro y fuera de una clase de carácter.

El Metacarácter de Alternación: ‘|’

El metacarácter ‘|’ (tubería) significa “o”. Te permite combinar múltiples expresiones en una única expresión que se corresponda con cualquiera de ellas. Las subexpresiones se conocen como alternativas.

Por ejemplo, Mike y Michael son expresiones separadas, pero Mike|Michael es una expresión que se se corresponde con ambas.

Se pueden usar paréntesis para limitar el ámbito de las alternativas. Podría haber acortado la expresión anterior que se correspondía con Mike o Michael con un uso creativo de los paréntesis. La expresión Mi(ke|chael) es equivalente. Probablemente yo usaría la primera expresión en la práctica, sin embargo, ya que es más legible y por lo tanto más mantenible.

Correspondencia con Objetos Opcionales: ‘?’

El metacarácter ‘?’ (interrogación) significa opcional. Se coloca después de un carácter que está permitido, pero no requerido, en un determinado punto de una expresión. La interrogación sólo hace referencia al carácter inmediatamente anterior.

Si quisiera encontrar las versiones británica o americana de la palabra “flavor” usaría la expresión flavou?r, que se interpreta como “f, seguido de l, seguido de a, seguido de v, seguido de o, seguido de una u opcional, seguido de r.”

Los Otros Cuantificadores: ‘+’ and ‘*’

Como la interrogación, los metacaracteres ‘+’ (más) y ‘*’ (asterísco) afectan al número de veces que el carácter precedente puede aparecer en la expresión (con ‘?’ el carácter precedente puede aparecer 0 ó 1 veces). El metacarácter ‘+’ se corresponde con una o más apariciones del carácter precedente, mientras que ‘*’ se corresponde con cualquier número de apariciones, incluso 0.

Si estuviera intentando determinar el resultado de un partido de fútbol contando el número de veces que el comentarista dijo la palabra “gol” en una transcripción, podría usar la expresión regular go+l, que se correspondería con “gol”, así como con “gooooooooool” (pero no con “gal”).

Los tres metacaracteres, interrogación, más, y asterisco se conocen como cuantificadores porque influyen en la cantidad de el objeto al que hacen referencia.

El Cuantificador de Intervalo: ‘{}’

La metasecuencia ‘{min, max}’ te permite especificar el número de veces que un objeto concreto puede aparecer, proporcionando un mínimo y un máximo. La expresión regular go{1,5}l limitaría nuestro ejemplo anterior a palabras con entre 1 y 5 oes. La sequencia {0,1} es idéntica a la interrogación.

El Carácter de Escape: ‘\’

El metacarácter ‘\’ (barra invertida) se usa para escapar metacaracteres que tienen un significado especial, de forma que puedas usarlos como caracteres normales en los patrones. Por ejemplo, si quisieras encontrar los caracteres “?” o “\”, puedes precederlos por una barra invertida, lo que eliminaría su significado habitual: “\?” o “\\”.

Cuando se usa antes de un carácter ordinario, una barra invertida puede tener un significado diferente dependiendo del tipo de expresión regular que estés usando. Para expresiones regulares compatibles con perl (PCREs) puedes consultar la página de perldoc para expresiones regulares PCREs son extremadamente comunes; este tipo de expresiones se pueden usar en PHP, Ruby, y ECMAScript/Javascript, y muchos otros lenguajes.

Usando Paréntesis: ‘()’

La mayoría de herramientas de expresiones regulares te permitirán capturar un determinado subconjunto de una expresión mediante paréntesis. Podría encontrar la parte correspondiente al dominio de un URL usando una expresión como http://([^/]+). Separemos esta expresión en sus componentes para ver como funciona.

El principio de la expresión es bastante obvio: se corresponde con la secuencia “h - t - t - p - : - / - /”. Esta secuencia inicial está seguida por paréntesis, que se usan para capturar los caracteres que se correspondan con la subexpresión en su interior. Es este caso, la subexpresión es ‘[^/]+’, que se corresponde con cualquier carácter excepto “/” una o más veces. Para un URL como http://immike.net/blog/Some-blog-post, “immike.net” será capturado por los paréntesis.

¿Quieres saber más?

Sólo he tocado la superficie de lo que se puede hacer con expresiones regulares. Si quieres aprender más, consulta el libro de Jeffrey Friedl Mastering Regular Expressions. Friedl hizo un trabajo impresionante con este libro; su lectura es accesible y sorprendentemente amena e interesante, considerando la materia de la que trata.

Consulta la continuación de este artículo donde hago un repaso a las expresiones regulares más útiles para tareas de programación comunes.

Deja una Respuesta