Wextensible

Introducción a las expresiones regulares en JavaScript

Ejemplo de la complejidad de una expresión regular

Las expresiones regulares en JavaScript y en cualquier lenguaje son un recurso muy importante que todo programador empezará a usar más temprano que tarde. Porque aunque todos los problemas no se pueden resolver con expresiones regulares, si que hay muchos donde esta técnica nos ayudará. Es verdad que antes de empezar a usarlas asustan un poco, porque de entrada ya vemos un revoltijo de caracteres que parecen imposibles de leer. Estos temas pretenden un acercamiento a las expresiones regulares y que al final no resulten tan "ásperas".

La mejor forma de estudiar las expresiones regulares es practicar con ellas. La herramienta Probador de Expresiones Regulares nos servirá de ayuda. Se trata de una aplicación para buscar cadenas en un texto. Podemos poner los patrones y texto que iremos explicando en temas siguientes para observar el resultado. Las coincidencias encontradas serán resaltadas con dos colores alternativos rojo y azul cuando el modificador global esté activado. Si no lo estuviera sólo resaltaría la primera coincidencia en rojo. Cuando se hace una búsqueda se ofrece información relevante sobre algunas propiedades de la ejecución de la expresión regular.

En este primer tema haremos una introducción a las expresiones regulares. En uno siguiente explicaremos la sintaxis, pasando luego a ver los métodos de ejecución en JavaScript. Por último haremos un ejercicio para crear un patrón de expresión regular que nos permita validar si una dirección de email está bien escrita.

Declaraciones de expresiones regulares de JavaScript

Una expresión regular en JavaScript es un objeto que contiene un patrón de expresión regular. A veces confundimos estos dos términos por lo que intentaré aclarar qué es cada cosa. Una declaración de una expresión regular válida podría ser como la que sigue:

var  reg = /.../gmi;
    

El patrón es todo lo que está encerrado entre las barras, en este caso los tres puntos consecutivos. No son tres puntos suspensivos cualesquiera, puesto que como veremos más abajo, ciertos caracteres como este punto tienen un significado especial en el patrón. En este caso el punto busca cualquier caracter y ese patrón buscará tres caracteres seguidos. Opcionalmente el patrón se finaliza con uno o más modificadores. Estos son letras "g", "m" e "i" en cualquier orden. Por lo tanto ya estamos diferenciando entre patrón y sus modificadores y la propia expresión regular resultante de la declaración, la variable reg, que no es otra cosa que un objeto de JavaScript.

Realmente la anterior declaración es una forma abreviada de la instanciación del objeto global window.RegExp:

var reg = new RegExp("...", "gmi");
    

Como con otros métodos y propiedades del objeto window, podemos prescindir de su referencia. Esta segunda forma tiene la ventaja de poder declarar expresiones regulares dinámicamente, pues el primer argumento es una cadena de texto para el patrón y el segundo argumento opcional son los modificadores. En definitiva decimos que creamos una expresión regular cuando declaramos una instancia de RegExp.

Captura de pantalla del Developer Tools de un navegador con un punto de interrupción en el código JavaScript para mostrar las propiedades y métodos de una variable.
Figura. Métodos exec() y test() de un objeto de expresión regular en JavaScript.

Pero una vez creada tenemos que ejecutarla, para lo cual disponemos de otros métodos que usan esas expresiones regulares. Por un lado tenemos los métodos de String como texto.match(reg), texto.search(reg), texto.split(reg, limite) y texto.replace(reg, reemplazo). Se aplican por lo tanto a una cadena de texto, siendo el argumento reg una expresión regular. Por otro lado tenemos los métodos del propio objeto de expresión regular (ver Figura), que son reg.exec(cadena) y reg.test(cadena). También existe un método compile() pero es obsoleto y no debe usarse. Observe como ahora se aplican a una expresión regular, siendo el argumento la cadena sobre la que buscar.

Esto de encontrar los métodos de ejecución en diferentes objetos es algo lioso. Más de una vez tengo que ver si es un método de String o de la expresión regular. Pienso que todos deberían ser métodos de la expresión regular, pero bueno, así están las cosas y así hemos de aprenderlas.

Instanciación de una expresión regular y objeto RegExp

Si declaramos una expresión regular con var reg = new RegExp("...", "gmi"); o bien con la forma literal var reg = /.../gmi;, la variable reg es una instancia de expresión regular del objeto RegExp. Ambos se actualizan tras ejecutar un método. Estos métodos devuelven las coincidencias encontradas, pero también en el objeto RegExp podemos encontrar resultados.

El objeto RegExp contendrá los resultados de la última ejecución que ha ocurrido en la página. Así que si consultamos con RegExp los resultados hemos de hacerlo inmediatamente después de la ejecución de algún método. No hay que olvidar que los métodos de ejecución match() y exec() devuelven los resultados en un array. Además con el método replace() podemos también acceder con las plantillas string $&, $1, $2,... en su argumento replace. O usando arguments en una función de reemplazo. Todo esto lo veremos en un tema posterior sobre los métodos de ejecución. Por lo tanto no hay necesidad de acceder a los resultados a través del RegExp.

Además no se recomienda acceder a los resultados a través de RegExp por una cuestión de seguridad. Pues es díficil controlar si otra expresión regular en nuestro script o, lo que es peor, scripts de terceros pudieran estar también modificando el RegExp después de que nosotros ejecutáramos uno, con lo que suplantarían nuestros resultados. En la página de Mozilla Características obsoletas marca estas propiedades de RegExp como deprecated, lo que significa que aún siguen soportándose pero en un futura no lo serán (pasarán a obsolete).

En la herramienta para probar expresiones regulares encontrará información detallada sobre estos objetos. Con cada ejecución podrá ver que contiene cada uno de ellos con la estructura que se expone a continuación.

Propiedades de la instancia de expresión regular

Propiedades del array de resultados

Propiedades del objeto RegExp

A excepción de las propiedades index y lastIndex los navegadores Chrome, Firefox e Internet Explorer se comportan igual. Con esas propiedades hay algunas diferencias, pues son soportadas también por IE en el RegExp. De todas formas ya comenté que no es buena cosa obtener los resultados a partir de este objeto. Pero si lo hace tenga en cuenta que lo navegadores podrían dejar de soportarlo, como sucede con IE9 y posteriores al menos cuando accedemos dentro de un función de reemplazo en el método replace().