Ahora que sabemos lo que son las expresiones regulares, vamos a profundizar en las propiedades o flags que puede tener un objeto
const regexp = /M..z/ig;
Esta es una expresión regular que busca cualquier texto que contenga una "M"
seguida de dos carácteres cualquiera, seguida de una "z"
. Ahora que tenemos una expresión regular en la constante regexp
, un buen punto de partida sería analizar las diferentes propiedades.
Propiedades de una RegExp
Cada expresión regular creada, tiene unas propiedades definidas, donde podemos consultar ciertas características de la expresión regular en cuestión. Además, también tiene unas propiedades de comprobación para saber si un flag determinado está activo o no (que veremos más adelante):
Propiedades | Descripción |
---|---|
.source | Devuelve la expresión regular original definida (sin los flags). |
.flags | Devuelve los flags activados en la expresión regular. |
.lastIndex | Devuelve la posición donde detectó una ocurrencia en la última búsqueda. (Ver más adelante) |
Las dos primeras propiedades nos dan toda la información sobre la expresión regular definida:
const regexp = /M..z/ig;
regexp.source; // "M..z"
regexp.flags; // "ig"
Observa que también tenemos una propiedad denominada .lastIndex
. Esta propiedad se utiliza para lanzar búsquedas sucesivas y comprobar coincidencias (necesita tener el flag g activado). Lo explicaremos un poco más adelante.
Flags de una expresión regular
Los flags son uno o varios carácteres especiales que se escriben en un /
delimitadora de una expresión regular, o en el segundo parámetro del new RegExp()
:
const regexp = /reg/; // No tiene ningún flag activado
const regexp = /reg/i; // Tiene el flag "i" activado
const regexp = new RegExp(/reg/, "gi"); // Tiene el flag "g" activado
Se trata de una serie de carácteres que indican ciertos comportamientos especiales que se encuentran activos en la expresión regular definida:
Propiedades | Flag | Descripción |
---|---|---|
.global | g | Búsqueda global. Permite seguir buscando coincidencias en lugar de pararse al encontrar una. |
.ignoreCase | i | Le da igual mayúsculas y minúsculas. Se suele denominar insensible a mayús/minús. |
.multiline | m | Multilínea. Permite a ^ y $ tratar los finales de línea \r o \n . |
.unicode | u | Unicode. Interpreta el patrón como un código de una secuencia Unicode. |
.sticky | y | Sticky. Busca sólo desde la posición indicada por lastIndex . |
.dotAll | s | Establece si \n , \r , separación de párrafo o separación de línea deberían considerarse en los . |
.hasIndices | d | Establece si al ejecutar un .exec() el resultado deberá tener propiedad .indices . |
Cada uno de estos flags se pueden comprobar si se encuentran activos desde Javascript con su booleano asociado, una propiedad de la expresión regular:
const regexp = /manz/gi;
regexp.global; // true
regexp.flags.includes("g"); // equivalente al anterior
regexp.ignoreCase; // true
regexp.flags.includes("i"); // equivalente al anterior
regexp.multiline; // false
regexp.flags.includes("m"); // equivalente al anterior
regexp.sticky; // false
regexp.flags.includes("y"); // equivalente al anterior
regexp.unicode; // false
regexp.flags.includes("u"); // equivalente al anterior
regexp.dotAll; // false
regexp.flags.includes("s"); // equivalente al anterior
regexp.hasIndices; // false
regexp.flags.includes("d"); // equivalente al anterior
Vamos ahora a analizar cada uno de estos flags y a poner un ejemplo para comprenderlo mejor.
Búsqueda global (flag g)
Empecemos por la propiedad .global
(flag g). Partamos del siguiente ejemplo, donde definimos una expresión regular sin el flag global. Observa que al ejecutar el método .test()
para buscar coincidencias, encuentra la primera y no continua buscando. La propiedad .lastIndex
siempre devuelve 0
:
const text = `Hola Manz,
Te escribo para contarte que Manz no me parece
un nombre apropiado para una persona.
Deberías ser un gato.
Atentamente,
Manz (el gato)`;
const regexp = /M..z/;
regexp.lastIndex // 0
regexp.test(text); // true
regexp.lastIndex // 0
regexp.test(text); // true
regexp.lastIndex // 0
Sin embargo, vamos a hacer lo mismo con el flag de la búsqueda global activado. Comprobarás que en este caso, el método .test()
va buscando las coincidencias sucesivas y va devolviendo en .lastIndex
la posición donde las ha encontrado:
const regexp = /M..z/g;
regexp.lastIndex // 0
regexp.test(text); // true
regexp.lastIndex // 9 (primera línea)
regexp.test(text); // true
regexp.lastIndex // 45 (tercera línea)
regexp.test(text); // true
regexp.lastIndex // 138 (última línea)
regexp.test(text); // false (no encuentra más, reinicia búsqueda)
regexp.lastIndex // 0
Ten en cuenta que una vez .test()
devuelve false
, la búsqueda se reinicia y comenzarías a buscar desde el principio nuevamente.
Case sensitive (flag i)
La propiedad .ignoreCase
(flag i) establece un flag que indica que no debe fijarse en la diferencia de mayúsculas y minúsculas, sino considerarlas lo mismo. Como siempre, veámoslo con un ejemplo:
const regexp = /M..z/i;
regexp.test("Manz"); // true
regexp.test("manz"); // true
regexp.test("MANZ"); // true
const regexp = /M..z/;
regexp.test("Manz"); // true
regexp.test("manz"); // false
regexp.test("MANZ"); // false
Como se puede ver en el segundo caso, no tenemos flag i
, y por lo tanto, si tiene en cuenta la diferencia de mayúsculas y minúsculas.
Soporte multilínea (flag m)
La propiedad .multiline
(flag m), permite considerar el texto como un texto multilinea, es decir, si en la expresión regular se utilizan anclas de inicio ^
o final $
de línea (las veremos más adelante), la expresión regular tendrá en cuenta esos inicios para evaluarlos. Veamos el ejemplo, donde se comprenderá a la perfección:
const text = `Esto es una primera línea
Esto es una segunda línea
Manz (esta línea empieza por Manz)`;
text; // 'Esto es una primera línea\nEsto es una segunda línea\n\nManz (esta línea empieza por Manz)'
Si observamos esta constante de texto text
en la consola, veremos que nos sale algo similar a lo anterior. El carácter \n
simboliza que hay una nueva línea. Bien, si intentamos detectar con una expresión regular sin flag m la palabra "Manz"
utilizando el ancla ^
para indicar que Manz
está al comienzo, comprobaremos que no funciona:
const regexp = /^M..z/;
regexp.test(text); // false
Esto ocurre porque la expresión regular considera que la aparición Manz
no está al principio del \n
. Sin embargo, al utilizar el flag m, considerará los \n
como si fuera empezar una nueva línea:
const regexp = /^M..z/m;
regexp.test(text); // true
Soporte unicode (flag u)
La propiedad .unicode
(flag u) nos permite activar características relacionadas con Unicode, es decir, con una codificación extendida de carácteres específicos. Puede ser útil en algunos casos. Por ejemplo, el emoji 🤡 es un carácter unicode representado por U+1F921
, por lo que podríamos querer buscarlo indicando su código:
const text = "Hola amigos, soy un 🤡 que enseña a programar";
const regexp = /\u{1F921}/;
regexp.test(text); // false, características unicode no están activas
const regexp = /\u{1F921}/u;
regexp.test(text); // true, características unicode están activas
Observa que podemos escribir el emoji en HTML utilizando su código 🤡, simplemente escribiendo 🤡
.
RegExp «pegajosa» (flag y)
La propiedad .sticky
(flag y), cuando está activada, nos permite realizar una búsqueda con la expresión regular, pero sólo lo hace en la posición que marca la propiedad .lastIndex
. No intentará buscar en posiciones posteriores o anteriores, sólo aplica a la posición actual de .lastIndex
, por lo que también podría ser útil modificarla:
const text = "Hola Manz, soy el Manz el gato.";
const regexp = /M..z/y;
regexp.lastIndex // 0
regexp.test(text); // false (en la posición 0 no se encuentra nada que coincida)
regexp.lastIndex = 5;
regexp.test(text); // true (en la posición 5 justo está el texto Manz, que coincide)
regexp.lastIndex // 9 (donde termina la ocurrencia encontrada)
regexp.test(text); // false (en la posición 9 no se encuentra nada que coincida)
regexp.lastIndex // 0 (se ha reseteado)
Así pues, el nombre sticky
(pegajoso) hace referencia a que la búsqueda mediante la expresión regular se queda «pegada» o atascada y no continúa buscando.
Soporte separadores (flag s)
La propiedad .dotAll
(flag s) activa la posibilidad de que carácteres como \n
(nueva línea), \r
(retorno de carro), \u{2028}
(separador de línea) o \u{2029}
(separador de párrafo) se consideren dentro de los carácteres comodín con el .
, algo que no sucede por defecto. Veamos un ejemplo:
const text = `Hola
Manz`; // "Hola\nManz"
// Soporte de separadores
const regexp = /Hola.M..z/s;
regexp.test(text); // true, el flag s considera que separador \n es un carácter
// Soporte multilinea
const regexp = /Hola.M..z/m;
regexp.test(text); // false, sin flag s no se considera que \n sea un carácter
Recuerda que si vas a usar el formato \u{número}
necesitas tener también el flag u
activado.
Activa indices (flag d)
La propiedad .hasIndices
(flag d) activa la característica especial que hace que cuando utilicemos el método .exec()
, el resultado incorpore una propiedad especial llamada .indices
, que explicaremos más adelante:
const text = `Hola Manz,
¿Podrías traerme una cajita de Whiskas?
Atentamente,
Manz el gato.`;
// Con flag d activado
const regexp = /M..z/d;
const result = regexp.exec(text);
Object.keys(result).includes("indices"); // true
// Sin flag d activado
const regexp = /M..z/;
const result = regexp.exec(text);
Object.keys(result).includes("indices"); // false
Más adelante veremos para que sirve esta propiedad .indices
y el método .exec()
, ya que lo explicaremos en uno de los temas posteriores.