Expresiones regulares

Una expresión regular (regexp) es un patrón que sirve encontrar coincidencias de subcadenas en un texto. Esto es muy útil en varios contextos. Por ejemplo:

Validación

Una regexp puede comprobar si una subcadena cumple determinados criterios, por ejemplo, si es un número o si no contiene espacios en blanco.

Ejemplo: comprobar si es un número entero:

/^(+|-)?\d+$/ o también /^[+-]?\d+$/ o también /^[+-]?[0-9]+$/ Comienza (^) opcionalmente (?) por el carácter + o por el carácter -, por lo que puede que incluso no aparezcan ninguno de los 2; seguidamente vienen caracteres de cifras numéricas (\d) de los que al menos debe introducirse uno (+), y aquí acabará la cadena ($).

Búsqueda

Una regexp facilita patrones más potentes para buscar coincidencias que una simple búsqueda de subcadena, por ejemplo, comprobar la existencia en una cadena de las palabras "mail", "letter" o "correspondence" y la no existencia de las palabras "email","letterbox", "mailman", "mailer", etc.

Buscar y reemplazar

Podremos usar esta función combinada con la función replaceString para reemplazar en una cadena todas las ocurrencias de la subcadena & por & excepto cuando el & ya se encuentre seguido de la subcadena amp;.

División de cadenas

Una regexp puede ser usada para identificar dónde debería dividirse una cadena, por ejemplo, al encontrar tabulaciones en la misma.

Las expresiones regulares son construidas mediante expresiones, cuantificadores y metacaracteres. La expresión más simple es un carácter, por ejemplo: x ó 5. Una expresión también puede ser una serie de caracteres contenidos entre corchetes. [ABCD] genera una ocurrencia cuando encuentra A, B, C o D. Esta misma expresión podría ser escrita de la forma siguiente: [A-D]. La expresión para generar ocurrencias con cualquier letra del alfabeto será [A-Z].

Un cuantificador permite indicar el número de ocurrencias de una subcadena que deben darse. x{1,1} significa que debe generar solamente la ocurrencia de un carácter x. x{1,5} significa que debe generar solamente la ocurrencia si se da una secuencia de caracteres que contenga al menos una x pero no más de cinco.

En general las expresiones regulares no pueden ser usadas para comprobar un correcto anidamiento de corchetes o etiquetas. Por ejemplo, una expresión regular puede ser escrita para encontrar la etiqueta html de apertura <b> y su correspondiente etiqueta de cierre </b> si las etiquetas <b> no están anidadas, pero si las etiquetas <b> se encuentran anidadas, la misma expresión regular generará una ocurrencia con una etiqueta de apertura <b> con la etiqueta de cierre </b> equivocada. Para el texto <b>destacado<b>más destacado</b></b>, el primer <b> sería emparejado con el primer </b>, lo que no es correcto. Sin embargo, es posible escribir una expresión regular que permita generar las coincidencias de corchetes o etiquetas anidadas correctamente, pero solamente si el número de niveles de anidamiento es fijo y conocido. Si el número de niveles de anidamiento no es fijo y conocido, será imposible escribir una expresión regular que no falle.

Supongamos que queremos construir una expresión regular que genere coincidencias con números comprendidos entre 0 y 99. Al menos se requiere un dígito, así que comenzaremos con la expresión [0-9] {1,1}, que generará coincidencia con un único dígito una única vez. Esta expresión regular genera coincidencia con números comprendidos entre 0 y 9. Para generar coincidencias con números hasta 99, incrementaremos el número máximo de ocurrencias a 2, así que la expresión regular pasaría a ser [0-9] {1,2}. Esta expresión regular cumple con el requisito original de encontrar números comprendidos entre 0 y 99, pero también generará ocurrencias con números que existan en el medio de cadenas. Si queremos que el número que genere concurrencia sea la cadena completa, debemos usar los metacaracteres, ^ (acento circunflejo) y $ (dólar). Cuando ^ es el primer carácter en una expresión regular, significa que la expresión regular debe generar la ocurrencia desde el comienzo de la cadena. Cuando $ es el último carácter de la expresión regular, significa que la expresión regular debe generar coincidencia con el final de la cadena. La expresión regular, por tanto, pasaría a ser ^[0-9] {1,2}$. Los metacaracteres ^ y $ no son usados para buscar ocurrencias de ambos caracteres en la cadena, sino para indicar posiciones dentro de la cadena.

Determinados conjuntos de caracteres y cuantificadores son tan comunes que se les han asignado símbolos especiales para su representación. [0-9] puede ser reemplazado por el símbolo \d. El cuantificador que permite especificar una única ocurrencia {1,1}, puede ser reemplazado por la expresión en sí misma, Ejemplo: x{1,1} es lo mismo que x. Para nuestro generador, coincidencias de números comprendidos entre el 0 y el 99 podríamos escribirlo de la forma siguiente ^\d{1,2}$. También podría ser escrito como ^\d\d{0,1}$, por ejemplo: desde el comienzo de la cadena, genera ocurrencia de un número, seguido inmediatamente por 0 ó 1 dígito. En la práctica, podría ser escrito como ^\d\d?$. El carácter ? es el símbolo especial que equivale a cuantificador {0,1}, por ejemplo, 0 ó 1 ocurrencias. ? hace una expresión opcional. La expresión regular^\d\d?$ significa: desde el comienzo de la cadena, que haya coincidencia de un número, seguido inmediatamente por 0 ó 1 dígito más y seguido inmediatamente del final de la cadena.

Para escribir una expresión regular que genere una coincidencia con las palabras "mai" o "letter" o "correspondence" pero que no genere coincidencia con palabras que contengan las palabras "email", "mailman", "mailer" ni "letterbox", comenzaremos con la expresión regular que genere una coincidencia con la palabra "mail". Expresada en su totalidad la expresión regular sería m{1,1}a{1,1}i{1,1}l{1,1}, pero ya que una expresión de carácter es automáticamente cuantificada por {1,1}, podemos simplificar la regexp escribiendo mail, es decir, una "m" seguida de una "a" seguida de una "i" seguida de una "l". Ahora podemos usar la barra vertical |, que significa o, para incluir las otras dos palabras, así, nuestra regesp para generar coincidencia con cualquier de las tres palabras sería: mail|letter|correspondence. Genera coincidencia con "mail", o con "letter" o con "correspondence". Mientras esta regexp generará una coincidencia con cualquiera de las tres palabras indicadas, también generaría coincidencia con palabras con las que no queremos, por ejemplo, "email". Para impedir que la expresión regular genere coincidencias con palabras no deseadas, debemos indicarle que la coincidencia debe darse con el comienzo y el final de una palabra,es decir, la palabra completa. En primer lugar, cerraremos nuestra expresión regular entre paréntesis (mail|letter|correspondence). Los paréntesis agrupan expresiones, e identifican una parte de la expresión regular que se desea capturar en el parámetro numSubExpresion de esta función (recordar que si este parámetro es 0, identificará la expresión regular completa). Cerrar la expresión entre paréntesis nos permite usarla como un componente en expresiones regulares complejas. Para forzar la generación de coincidencia con la palabra completa, cerraremos la expresión regular con el metacarácter que indica límite de palabra \b: \b(mail|letter|correspondence)\b. Ahora la expresión regular significa: genera coincidencia de una palabra, seguida de la expresión regular entre paréntesis, seguido de un límite de palabra. El metacarácter \b genera coincidencia con una posición dentro de la expresión regular, no un carácter. Un límite de palabra es cualquier carácter no de palabra, por ejemplo, espacio, nueva línea o el comienzo o el final de una cadena.

Si queremos localizar en una cadena el carácter ampersand (&) con el fin de reemplazarlo por su código equivalente en html: & amp;, la expresión regular es &. Pero esta expresión regular también generará coincidencias con ampersands que ya hayan sido reemplazados por su equivalente html. Si queremos generar coincidencia solamente con aquellos ampersands que no se encuentren seguidos de la cadena amp;, para ello necesitaremos el metacarácter de negación (?!__). La expresión regular, por tanto, podrá ser escrita: &(?!amp;).

Si queremos generar coincidencias de las palabras "Eric" y "Eirik" en una cadena, dos posibles soluciones son \b(Eric|Eirik)\b y \bEi?ri[ck]\b. El metacarácter de límite de palabra \b se necesita para evitar la generación de coincidencias, por ejemplo, con cadenas como "Erica". Atención: la segunda expresión regular generará coincidencia con más palabras que las indicadas: "Eric", "Erik", "Eiric" y "Eirik".

Caracteres y abreviaturas para conjuntos de caracteres

c

En una expresión regular cualquier carácter se representa a sí mismo, salvo si el carácter es un carácter que se usa como metacarácter o cuantificador. Así, c se corresponde con el carácter c, pero ^ no representa al carácter ^ ya que es un metacarácter que se usa identificar una posición en la cadena.

\c

Un carácter precedido de la barra de directorios (\) se corresponde con ese carácter en sí. Es decir, en una expresión regular "\c" y "c" identifican indistintamente al carácter cy la cadena \^ se corresponde con el carácter ^, no es tomado como metacarácter.

\a

Equivale al carácter ASCII de campana (BEL, 0x07).

\f

Equivale al carácter ASCII de salto de página (FF, 0x0C).

\n

Equivale al carácter ASCII de nueva línea (LF, 0x0A, Unix newline).

\r

Equivale al carácter ASCII de retorno de carro (CR, 0x0D).

\t

Equivale al carácter ASCII de tabulador horizontal (HT, 0x09).

\v

Equivale al carácter ASCII de tabulador vertical (VT, 0x0B).

\xhhhh

Equivale al carácter Unicode correspondiente al número hexadecimal hhhh (entre 0x0000 y 0xFFFF). \0ooo (i.e., \zero ooo) equivale al carácter ASCII/Latin-1 character que se corresponde con el número octal ooo (entre 0 y 0377).

. (dot)

Equivale a cualquier carácter (incluido nueva línea).

\d

Equivale a un dígito.

\D

Equivale a un no-dígito.

\s

Equivale a un espacio en blanco.

\S

Equivale a un no-espacio en blanco.

\w

Equivale a un carácter (dígito o letra).

\W

Equivale a un no-carácter (espacio en blanco, fin de línea, etc.).

Si en un expresión regular queremos incluir el carácter \ como carácter, tendremos que escribirlo dos veces: \\.

Dado que el carácter \ es el delimitador de las secuencias des escape en fórmulas, si en una fórmula queremos establecer una expresión regular, por ejemplo "\S", para que el sistema no lo tome como una secuencia de escape debemos escribirlo dos veces; es decir "\S".

Conjuntos de caracteres

Los corchetes implican generar coincidencia con cualquier carácter contenido entre ellos. Las abreviaturas de conjuntos de caracteres descritas anteriormente pueden aparecer en un conjunto de caracteres entre corchetes. Los caracteres no tienen ningún significado especial cuando van entre corchetes, excepto en los casos siguientes:

^

El acento circunflejo niega el conjunto de caracteres cuando es el primer carácter (por ejemplo, inmediatamente después del corchete de apertura). [abc] genera ocurrencia con cualquier carácter "a" o "b" o "c" de la cadena, pero [^abc] generará una ocurrencia con cualquier carácter distinto de "a", "b" o "c".

El guión indica un rango de caracteres. [W-Z] generará una ocurrencia con cualquier carácter comprendido entre la "W" y la "Z"; es decir, con "W" o "X" o "Y" o "Z".

Cuantificadores

Por defecto, una expresión regular es automáticamente cuantificada como {1,1}, es decir, solamente podría generar una única ocurrencia. En la lista que presentamos a continuación, E significa "expresión". Una expresión es un carácter, o una abreviatura de conjunto de caracteres, o un conjunto de caracteres entre corchetes, o una expresión entre paréntesis.

E?

Genera cero o una ocurrencias de E. Este cuantificador significa "la expresión anterior es opcional", ya que generará ocurrencia tanto si encuentra la expresión en la cadena como si no. E? es lo mismo que E{0,1}. Ejemplo: dientes? generará coincidencia con "diente" o "dientes".

E+

Genera cero o más ocurrencias de E. E+ es lo mismo que E{1,}. Ejemplo: 0+ generará coincidencia con "0", "00", "000", etc.

E*

Genera cero o más ocurrencias de E. E* es lo mismo que E{0,}. El cuantificador * suele ser usado equivocadamente cuando debería usarse +. Ejemplo: si \s*$ es usado en una expresión para generar ocurrencias con cadenas que terminen con un espacio en blanco, generaría ocurrencia con cualquier cadena porque \s*$ quiere decir "Genera ocurrencia con cero o más espacios en blanco seguidos de un final de cadena". La expresión regular correcta para generar ocurrencia con cadenas que tengan al menos un espacio en blanco al final es \s+$.

E{n}

Genera n ocurrencias exactas de E. E{n} es lo mismo que repetir E n veces. Ejemplo: x{5} es lo mismo que xxxxx. Es también lo mismo que x{5,5}.

E{n,}

Genera ocurrencias de al menos n ocurrencias de E. E{,m}: genera ocurrencias de como mucho n ocurrencias de E. E{,m} es lo mismo que E{0,m}E{n,m}

Para aplicar un cuantificador a más que simplemente al carácter previo, utilizaremos paréntesis para agrupar los caracteres en una expresión. Por ejemplo, tag+ genera ocurrencia de una "t" seguida de una "a" seguida de al menos una "g", mientras que (tag)+ generará al menos una ocurrencia de "tag".

Los cuantificadores son "avariciosos". Siempre generan ocurrencia con tanto texto como les sea posible. Por ejemplo, 0+ generará ocurrencia con el primer 0 que encuentre pero también con los siguientes ceros consecutivos después del primero. Aplicado a 2005 generará coincidencia con 20005.

Metacaracteres

Los metacaracteres permiten declarar posiciones dentro del texto en el punto en el que ocurran en la expresión regular, pero no generan coincidencia con carácter alguno. En la siguiente lista E equivale a cualquier expresión:

^

El acento circunflejo indica comienzo de la cadena. Si en una expresión regular quisiésemos usar el acento circunflejo ^ como carácter y no como metacarácter tendríamos que escribirlo precedido por el carácter de escape: \^. Por ejemplo ^#include solamente generará ocurrencia con cadenas que comiencen con los caracteres "#include". Cuando el acento circunflejo es el primer carácter de un grupo de caracteres, recordemos que tiene un significado especial (ver el apartado dedicado a los conjuntos de caracteres de este mismo capítulo).

$

El dólar indica fin de cadena. Por ejemplo \d\s*$ generará ocurrencia con cadenas que finalicen con un número opcionalmente seguido en un espacio en blanco. Si quisiésemos comprobar ocurrencias del literal $, tendríamos que escribirlo precedido por el carácter de escape: $

\b

Límite de palabra. Por ejemplo, la expresión regular\bOK\b significa generar ocurrencia de la letra "O" seguida de la letra "K", tras un límite de palabra (por ejemplo, el comienzo de la cadena o un espacio en blanco). Destacar que este metacarácter no genera ocurrencia con ningún espacio en blanco, por lo que si escribimos (\bOK\b) y encontramos una ocurrencia, ésta será de la cadena OK, incluso si la cadena es "Todo está OK ahora".

\B

No-límite de palabra. Este metacarácter es el contrario a \b. Por ejemplo, si buscamos \Bno\B en la cadena "Esto no" no se generaría ocurrencia alguna (el espacio y el final de la cadena no son no-límites de palabra), si generaría coincidencia en "tonos".

(?=E)

Aserción. Este metacarácter es verdadero cuando la expresión genere coincidencia en este punto en la expresión regular. Por ejemplo, const(?=\s+char) genera ocurrencia con "const" siempre que vaya seguido por "char" como por ejemplo en "static const char *". const\s+char, aplicado sobre la cadena "static const char *" generará coincidencia con "const char".

(?!E)

Negación. Este metacarácter es verdadero cuando la expresión genere coincidencia en este punto en la expresión regular. Por ejemplo, const(?!\s+char) genera ocurrencia con "const" excepto cuando vaya seguido por la cadena "char".