Expresiones regulares en javacript. Teoría y ejemplos
El siguiente artículo es una adaptación de uno de los capítulos de expresiones regulares del libro de O’reilly Javascript Cookbook. Por lo que algunos nombres, y ejemplos de frases los he conservado en inglés. También he eliminado algunas secciones, en este artículo tan sólo se conservar al rededor de 1/3 de todo el contenido original, conservando la teoría más básico y algunos ejemplos prácticos.
Introducción
Las expresiones regulares son patrones de búsqueda que se pueden utilizar para encontrar el texto que coincide con un patrón determinado. Por ejemplo, en el último capítulo, buscamos la subcadena Cookbook dentro de una cadena más larga:
```var testValue = “This is the Cookbook’s test string”; var subsValue = “Cookbook”;
var iValue = testValue(subsValue); ```
devuelve el valor 12 que es el indice de la subcadena
Este fragmento de código funcionó porque estábamos buscando una coincidencia exacta. Pero lo que si queremos una búsqueda más general? Por ejemplo, queremos buscar para Cook y la palabra Book, en cadenas como “Joe’s Cooking Book” o “JavaScript Cookbook”?
Cuando estamos en busca de cadenas que coinciden con un patrón en lugar de una cadena exacta, tenemos que usar expresiones regulares. Podemos tratar de hacerlo con las funciones de String funciones, pero al final, es realmente fácil de usar expresiones regulares, aunque la sintaxis y el formato es un poco extraño y no necesariamente “amigable”.
Una expresion regular literal
RegExp puede ser un literal y un objeto. Para crear un literal RegExp, se utiliza la siguiente sintaxis:
var re = /regular expression/;
El patrón de expresión regular se encuentra entre la apertura y el cierre de las barras diagonales. Tenga en cuenta que este modelo no es una cadena: no desea utilizar comillas simples o dobles alrededor del patrón, a menos que las propias citas son parte de la estructura de partido.
Las expresiones regulares se componen de caracteres, ya sea solo o en combinación con caracteres especiales, que proporcionan para ajustar más complejo. Por ejemplo, la siguiente es una expresión regular para un patrón que coincida con una cadena que contiene la palabra Shelley y la palabra Powers, en ese orden y separados por uno o más espacios en blanco:
var re = /Shelleys+Powers/;
Los caracteres especiales en este ejemplo son la barra invertida (), que tiene dos fines: o bien se utiliza con un carácter regular, para indicar que se trata de un carácter especial, o se usa con un carácter especial, como el signo más (+ ), para indicar que el caracter debe ser tratada literalmente. En este caso, la barra invertida se utiliza con “s”, que transforma la letra s de un carácter especial la designación de un espacio en blanco, como un espacio, tabulación, avance de línea, etc. El carácter especial s es seguido por el signo más, s+, que es una señal para que coincida con el carácter anterior (en este ejemplo, un espacio en blanco) una o más veces. Esta expresion regular funcionará con:
Shelley Powers
Pero también con la siguiente cadena
Shelley Powers
No funcionará con el siguiente texto
No importa la cantidad de espacio en blanco entre Shelley y Powers, por el uso de s+. Sin embargo, el uso del signo más se requieren por lo menos un espacio en blanco.
A continuación una tabla con la mayoría de los caracteres especiales en las aplicaciones de JavaScript.
<h5>Caracteres especiales para las expresiones regulares con Javascript</h5>
<table width="100%" border="1" cellspacing="0"><colgroup > <col /> <col /> <col /></colgroup>
<thead>
<tr>
<th scope="col" valign="top">Caracter</th>
<th scope="col" valign="top">Coincidencia/Patrón</th>
<th scope="col" valign="top">Ejemplo</th>
</tr>
</thead>
<tbody>
<tr>
<td valign="top">^</td>
<td valign="top">Busca la coincicencia al inicio de la cadena</td>
<td valign="top">/^Esto/ coincidiría en: "Esto es una cadena"</td>
</tr>
<tr>
<td valign="top">$</td>
<td valign="top">Coincidencia con el final del input o del texto</td>
<td valign="top">/final?/ coincidiría con: "Esto es el final"</td>
</tr>
<tr>
<td valign="top">*</td>
<td valign="top">Coincide ninguna o muchas veces</td>
<td valign="top">/mi*/ coincidiría con: "miiiii" y tambien con "mi"</td>
</tr>
<tr>
<td valign="top">?</td>
<td valign="top">Coincide cero o una vez</td>
<td valign="top">/ap?/ coincidiría con: "apple"</td>
</tr>
<tr>
<td valign="top">+</td>
<td valign="top">Coincide una o muchas veces</td>
<td valign="top">/ap+/ coincidiría con: "apple"</td>
</tr>
<tr>
<td valign="top">{n}</td>
<td valign="top">Coincidiría exactamente n veces</td>
<td valign="top">/ap{2}/ coincidiría con: "apple" pero no con "apie"</td>
</tr>
<tr>
<td valign="top">{n,}</td>
<td valign="top">Coincidiría n o mas veces</td>
<td valign="top">/ap{2,}/ coincidiría con todas las p en: "apple" y "appple" pero no en "apie"</td>
</tr>
<tr>
<td valign="top">{n,m}</td>
<td valign="top">Coincidiría al menos n y como máximo m veces</td>
<td valign="top">/ap{2,4}/</td>
</tr>
<tr>
<td valign="top">.</td>
<td valign="top">Para cualquier caracter salvo salto de linea</td>
<td valign="top">/a.e/ coincide con "ape" y "axe"</td>
</tr>
<tr>
<td valign="top">[...]</td>
<td valign="top">Cualquier caracter dentro de los parentesis</td>
<td valign="top">/a[px]e/ coincidiría “ape” y “axe” pero no “ale”</td>
</tr>
<tr>
<td valign="top">[^...]</td>
<td valign="top">Cualquier caracter menos los que están entre paréntesis</td>
<td valign="top">/a[^px]/ coincidiría “ale” pero no “axe” o “ape”</td>
</tr>
<tr>
<td valign="top">b</td>
<td valign="top">Coincide con el primer límite de la palabra</td>
<td valign="top">/bno/ coincidiría con el primer “no” en la palabra “nono”</td>
</tr>
<tr>
<td valign="top">B</td>
<td valign="top">Coincide con el último límite de la palabra</td>
<td valign="top">/Bno/ coincide con el ultimo “no” en “nono”</td>
</tr>
<tr>
<td valign="top">d</td>
<td valign="top">Para dígitos de 0 a 9</td>
<td valign="top">/d{3}/ coincide 123 en “Now in 123”</td>
</tr>
<tr>
<td valign="top">D</td>
<td valign="top">Cualquier caracter no digito</td>
<td valign="top">/D{2,4}/ coincide con “Now " en “Now in 123”</td>
</tr>
<tr>
<td valign="top">w</td>
<td valign="top">Cualquier caracter que sea una letra, digito o barra baja</td>
<td valign="top"></td>
</tr>
<tr>
<td valign="top">W</td>
<td valign="top">Lo contraio a lo anterior</td>
<td valign="top">/W/ Coincidiría “%” en “100%”</td>
</tr>
<tr>
<td valign="top">n</td>
<td valign="top">Para los saltos de linea</td>
<td></td>
</tr>
<tr>
<td valign="top">s</td>
<td valign="top">Un solo espacio en blanco</td>
<td></td>
</tr>
<tr>
<td valign="top">S</td>
<td valign="top">Un solo caracter pero que no sea un espacio en blanco</td>
<td></td>
</tr>
<tr>
<td valign="top">t</td>
<td valign="top">Una tabulacion</td>
<td></td>
</tr>
<tr>
<td valign="top">(x)</td>
<td valign="top">paréntesis de captura</td>
<td valign="top">Recuerda los caracteres coincidentes</td>
</tr>
</tbody>
</table>
<h4></h4>
<h4>Una expresión regular con Object</h4>
La expresión regular es un objeto de JavaScript, así como un literal, por lo que también se pueden crear con un constructor, de la siguiente manera:
```var re = new RegExp("Shelleys+Powers");```
Cuándo usar cada tipo? El literal RegExp se compila cuando el script se evalúa, por lo que debe utilizar un literal RegExp cuando sabes que la expresión no va a cambiar. Una versión compilada es más eficiente. Utilice el constructor cuando cambia la expresión o se va a construir o asignar en tiempo de ejecución.
<h2 >Ejemplo: Probar si existe una cadena</h2>
Vamos a comprobar si una cadena está contenida en otra cadena.
Utilizar una expresión regular JavaScript para definir un patrón de búsqueda, y luego aplicar el patrón contra de la cadena a buscar, mediante el método RegExp. Haremos que coincida con cualquiera cadena que tenga las dos palabras Cook y Book en ese orden:
Solución.
```var cookbookString = new Array();
cookbookString[0] = "Joe's Cooking Book";
cookbookString[1] = "Sam's Cookbook";
cookbookString[2] = "JavaScript CookBook";
cookbookString[3] = "JavaScript BookCook";
// patrón de búsqueda
var pattern = /Cook.*Book/;
for (var i = 0; i < cookbookString.length; i++)
alert(cookbookString[i] + " " + pattern.test(cookbookString[i]));
La primera y tercera cadenas tiene un resultado positivo, mientras que la segundo y cuarta no.
El método de prueba RegExp toma dos parámetros: la cadena de prueba, y un modificador opcional. Se aplica la expresión regular con la cadena y devuelve true si hay una coincidencia, falso si no hay.
En el ejemplo, el patrón es la palabra Cook y la palabra Book, que aparecen en algún lugar en la cadena, la palabra Book después de la palabra Cook. Puede haber el númro de caracteres que sea entre las dos palabras, incluyendo que no haya nada indicados por los carácteres espciales, punto (.) y el asterisco (*)
El decimal en las expresiones regulares es un carácter especial que coincide con cualquier carácter excepto el carácter de nueva línea. En el patrón de ejemplo, el decimal es seguido por un asterisco, que coincide con el carácter anterior cero o más veces. Combinados, generan un patrón de coincidencia con cero o más de cualquier carácter, excepto una línea nueva.
Ejemplo: Comprobando las coincidencias entre mayúsculas - minúsculas en una cadena
Quieres comprobar si una cadena está contenida en otra cadena, pero no importar si el caracter mayuscula-minuscula. Para ello, a la hora de crear la expresion regular, hay que utilizar el indicador para ignorar (i) al final de la expresion regular.
```var cookbookString = new Array();
cookbookString[0] = “Joe’s Cooking Book”; cookbookString[1] = “Sam’s Cookbook”; cookbookString[2] = “JavaScript CookBook”; cookbookString[3] = “JavaScript cookbook”; // patrón de busqueda var pattern = /Cook.*Book/i; for (var i = 0; i < cookbookString.length; i++) { alert(cookbookString[i] + “ “ + pattern.test(cookbookString[i],i)); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Los cuatro patrones coindicen.
<h4>Flags o indicadores de las expresiones regulares</h4>
<table width="100%" border="1" cellspacing="0"><colgroup > <col /> <col /></colgroup>
<thead>
<tr>
<th scope="col" valign="top">Flag</th>
<th scope="col" valign="top">Significado</th>
</tr>
</thead>
<tbody>
<tr>
<td valign="top">g</td>
<td valign="top">Coincidencia global: comprueba en toda la cadena, en lugar de detenerse cuando encuentra la primera coincidencia.</td>
</tr>
<tr>
<td valign="top">i</td>
<td valign="top">ignora el caso</td>
</tr>
<tr>
<td valign="top">m</td>
<td valign="top"><a name="line in"></a>Se aplica comenzar y terminar la línea de caracteres especiales (^ y $, respectivamente) a cada línea en una cadena de varias líneas</td>
</tr>
</tbody>
</table>
<h2 >Ejemplo: Encontrar y destacar todas las instancias de un patrón</h2>
Quieres encontrar todas las instancias de un patrón dentro de una cadena. Para ello hay que utilizar el método exec en la expresión regular con el flag (g).
Vamos a decir como ejemplo cualquier palabra que empieza con t y termina con e y nos dará igual el numero de caracteres entre ellos.
var searchString = “Now is the time and this is the time and that is the time”; var pattern = /tw*e/g; var matchArray;
var str = “”; while((matchArray = pattern.exec(searchString)) != null) { str+=”at “ + matchArray.index + “ we found “ + matchArray[0] + “ “; } document.getElementById(“results”).innerHTML=str;
1
2
3
4
5
El metodo exec de la expresion regular, devuelve null si no se encuentra la coincidencia, o un array con la información encontrada. En el array se encuentra el valor actual que ha encontrado, el índice de la cadena donde se encuentra la coincidencia,cualquier coincidencias de subcadenas entre paréntesis, y la cadena original.
<h2 >Ejemplo: Reemplazar un patrón por una nueva cadena</h2>
Para ello hay que usar el metodo replace del objeto String con una expresión regular.
var searchString = “Now is the time, this is the time”; var re = /tw{2}e/g; var replacement = searchString.replace(re, “place”); alert(replacement); // Now is the place, this is the place
1
2
3
4
5
<h2 >Ejemplo: Intercambio de palabras en una cadena usando paréntesis de captura</h2>
Hay que usar paréntesis de captura y una expresión regular para encontrar y recordar los dos nombres de la cadena, y revertirlos.
En el ejemplo vamos a intercambiar el nombre de orden, poniendo el nombre al final y el apellido primero.
var name = “Pedro Ventura”; var re = /^(w+)s(w+)$/; var newname = name.replace(re,”$2, $1”);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Los paréntesis de captura nos permitirá no sólo para que coincida con los patrones preestablecidos en una cadena, sino que además hace referencia al subcadenas coincidentes. Las cadenas coincidentes son referenciadas numericamente de izquierda a derecha y son representadas con el uso de "$1" y "$2" en el método replace de String.
Como las dos palabras están separadas por un espacio, es facil de crear la expresión regular, que recoge el nombre (las dos palabras), y el nombre será accesible usando "$1" y el apellido con "$2".
<h5>Patrones especiales para String.replace</h5>
<table width="100%" border="1" cellspacing="0"><colgroup > <col /> <col /></colgroup>
<thead>
<tr>
<th scope="col" valign="top">Patrón</th>
<th scope="col" valign="top">Propósito</th>
</tr>
</thead>
<tbody>
<tr>
<td valign="top">$$</td>
<td valign="top">Permite remplazar literalmente el signo dolar($)</td>
</tr>
<tr>
<td valign="top">$&</td>
<td valign="top">Inserta la subcadena coincidente</td>
</tr>
<tr>
<td valign="top">$`</td>
<td valign="top">Inserta parte de la cadena antes de la coincidencia</td>
</tr>
<tr>
<td valign="top">$’</td>
<td valign="top">Inserta parte de la cadena después de la coincidencia</td>
</tr>
<tr>
<td valign="top">$n</td>
<td valign="top">Inserta todos los valores capturados por parentesis en la expresión regular.</td>
</tr>
</tbody>
</table>
<h2 >Ejemplo: Reemplazar HTML Tgas por sus respectivas entidades</h2>
A modo simple, convertiremos los guiones de las etiquetas (<>) en sus rectivas entidades <>
var pieceOfHtml = “<p>This is a paragraph</p>”; pieceOfHtml = pieceOfHtml.replace(/</g,”<”); pieceOfHtml = pieceOfHtml.replace(/>/g,”>”); document.getElementById(“searchResult”).innerHTML = pieceOfHtml; ```
Añado el siguiente enlace http://xregexp.com/ que es una librería de expresiones regulares en javascript bastante buena.