Expresiones regulares

¿Qué son las expresiones regulares?

Una expresión regular es una secuencia de caracteres que forma un patrón. A diferencia de las cadenas de texto (donde cada carácter dentro de la cadena de texto es específico), en las expresiones regulares se puede generalizar el contenido de el carácter.

Por ejemplo se puede definir si el carácter:

  • Es alfabético sin importar que letra se utilice. *
  • Es numérico sin importar el valor del número.
  • Es alfanumérico cualquier letra o número.
  • No es alfanumérico como guiones, puntos, espacios en blanco, cambios de línea.

* Nota:
De manera predeterminada las expresiones regulares consideran únicamente los caracteres ASCII (alfabéticos) como caracteres alfabéticos. Algunos caracteres (en español) que no son tomados en cuenta como caracteres alfabéticos por las expresiones regulares son: caracteres acentuados, ñ o diéresis.
Si necesitas esta funcionalidad puedes incluir un plugin como http://xregexp.com/plugins/ o incluir dentro de la expresión regular los caracteres que necesites utilizar.

¿Para qué sirven las expresiones regulares?

En este caso (utilizando JavaScript en el front end) se pueden utilizar para verificar que los valores introducidos en un formulario cumplan con un cierto formato,  para dar formato a ciertas cadenas de texto o para reemplazar caracteres o palabras dentro de bloques de texto.

En otro contexto (sistemas operativos o aplicaciones) se utilizan para buscar archivos por nombre o extensión, también para buscar y reemplazar términos dentro de un archivo de texto.

Uso

Vamos a utilizar el método test que tienen las expresiones regulares para evaluar texto.

test
Éste método evalúa la cadena de texto que se le pasa como parámetro.
Devuelve true si cumple con el patrón definido en la expresión regular.
Si no cumple con el patrón devuelve false.
Resulta útil si queremos verificar que la cadena de texto coincida con el patrón definido.

var js = /javascript/   
js.test('js')
js.test('javascript')

/*
La expresión regular /javascript/ indica que el valor 
a comparar debe de contener el término "javascript"
*/

js.test('Un lenguaje que se puede utilizar con html es javascript') 

Construir Patrones

Ya que vimos como crear una expresión regular y cómo evaluar texto ahora vamos a construir distintos patrones utilizando metacaracteres.

Caracteres

Carácter Descripción
. El punto representa cualquier carácter excepto cambio de línea.
\d Representa cualquier dígito (número). Equivalente de [0-9]
\D Representa cualquier carácter excepto un número. Equivalente [^0-9]
\w Representa cualquier carácter alfanumérico (letras, números y guión bajo).
\W Representa cualquier carácter no alfanumérico (que no sean letras, números o guión bajo).
\s Representa cualquier carácter en blanco (espacio, tabulación, cambio de línea).
\S Representa cualquier carácter excepto espacio, tabulación, cambio de linea.
/*
El año debe de tener cuatro digitos para ser válido
*/
  var year =  /\d\d\d\d/
  year.test("2014")
  year.test(2014)
  
  year.test("14")
  year.test(14)
  year.test("'14")  
  
/*
El formato de la fecha debe de tener:
- Dos dígitos para el día
- Dos dígitos para el mes  
- Cuatro dígitos para el año
- Un caracter para separar día y mes
- Un caracter para separar mes y año
  
Casi cualquier caracter es válido para utilizarse como separador, 
incluido el espacio en blanco.
*/
  
  var fecha = /\d\d.\d\d.\d\d\d\d/
  fecha.test("17 01 2014")
  fecha.test("17.01.2014")
  fecha.test("17/01/2014")
  fecha.test("17-01-2014")
  
  
/*  En la siguiente expresión el mes está definido con tres iniciales  */

  var fecha = /\d\d.\w\w\w.\d\d\d\d/
  // Son válidas
  fecha.test("17 ene 2014")
  fecha.test("17.ene.2014")
  fecha.test("17/ene/2014")
  fecha.test("17-ene-2014")

// No es válida porque el mes tiene más de tres letras
  fecha.test("17 enero 2014")

Inicio / Fin

Carácter Descripción
^ La cadena de texto tiene que comenzar con lo indicado.
$ La cadena de texto tiene que terminar con lo indicado.
var inicio = /^js/
var fin = /js$/  

inicio.test("js se puede utilizar con html")
inicio.test("Un lenguaje que se puede utilizar con html es js")

fin.test("js se puede utilizar con html")
fin.test("Un lenguaje que se puede utilizar con html es js")

/*
Para ser válida  la fecha debe de comenzar con el día 
y terminar con el año
*/

var fecha = /^\d\d.\w\w\w.\d\d\d\d$/

// Son válidas
fecha.test("17 ene 2014")
fecha.test("25 feb 2014")

// No son válidas
fecha.test("2014.ene.17")
fecha.test("17/01/2014")
fecha.test("17-ene-2014")

Repeticiones

Carácter Descripción
? El carácter que precede debe aparecer 0 o 1 vez en el patrón.
+ El carácter que precede debe aparecer 1 o más veces en el patrón.
* El carácter que precede debe aparecer 0 o más veces en el patrón.
{#} Cuando solo hay un parámetro (número) indica el número de veces exactas que debe aparecer en el texto.
{#,#} Cuando hay dos parámetros (números) indica que debe aparecer entre n1 y n2 veces dentro del patrón.
{#,} Cuando hay dos parámetros (número, vacío) indica que el carácter debe aparecer al menos n1 veces (no hay límite superior de apariciones).
/*
Vamos a utilizar los caracteres de repetición para
hacer más corta la expresión regular.
Para ser válida  la fecha debe de comenzar con el día 
y terminar con el año.
*/

var fecha = /^\d\d.\w\w\w.\d\d\d\d$/
var fecha_abreviada = /^\d{2}.\w{3}.\d{4}$/

// Son válidas
fecha_abreviada.test("17 ene 2014")
fecha_abreviada.test("25.feb.2014")

/* 
Si queremos que la fecha se pueda definir  
sin  delimitador se utilizamos ? después del punto
*/

var fecha_abreviada = /^\d{2}.?\w{3}.?\d{4}$/
// Son válidas
fecha_abreviada.test("17ene2014")
fecha_abreviada.test("17-ene-2014")

/*
No es válida ya que el delimitador está utilizando 
dos caracteres en lugar de uno solo
*/
fecha_abreviada.test("25--feb--2014")

/* Si queremos que el año se pueda indicar en 2 cifras */

var fecha_abreviada = /^\d{2}.?\w{3}.?\d{2,4}$/

// Son válidas
fecha_abreviada.test("17ene14")
fecha_abreviada.test("17ene2014")
fecha_abreviada.test("17-ene-14")
fecha_abreviada.test("17-ene-2014")

/*
Un error, como permitimos que se pueda dar un rango 
de dos a cuatro cifras esta fecha es válida.
*/

fecha_abreviada.test("25-feb-204")

/* 
No es válida ya que el delimitador está utilizando 
dos caracteres en lugar de uno solo
*/
fecha_abreviada.test("25--feb--2014")

/*
Vamos a corregir el error del año utilizando grupos
*/

Grupos

Carácter Descripción
[] Se utiliza para definir un conjunto de caracteres. Se pueden definir rangos de valores utilizando un guión. Dentro de este conjunto no se interpretan los caracteres especiales.
() Capturan patrones internos. Al capturar un patrón, este queda en memoria para poder utilizarse después. Si se quiere evitar la captura de coincidencias hay que utilizar ?: antes de definir el patrón.
^ Cuando se utiliza dentro de un grupo como primer carácter indica que las coincidencias no deben de contener el patrón definido.
| Crea patrones opcionales
\ Escapa caracteres especiales
/* Corchetes */

var vocales = /[aeiou]/

vocales.test("a")
vocales.test("x")

var consonantes = /[^aeiou]/

consonantes.test("a")
consonantes.test("x")


/* Rangos */
var alfabeto_minusculas = /[a-z]/

alfabeto_minusculas.test('e')
alfabeto_minusculas.test('A')


var alfabeto_mayusculas = /[A-Z]/

alfabeto_mayusculas.test('e')
alfabeto_mayusculas.test('A')


var uno_al_cinco = /[1-5]/

uno_al_cinco.test(4)
uno_al_cinco.test(9)


/*
Paréntesis

Para evitar que los términos sean almacenados hay que utilizar
?: antes del patrón a evaluar dentro del paréntesis

*/

var cantidad_de_numeros = /^(?:\d{2}||\d{4})$/

cantidad_de_numeros.test(10)
cantidad_de_numeros.test(2010)

cantidad_de_numeros.test(1)
cantidad_de_numeros.test(210)
cantidad_de_numeros.test(20101)

/*
  Ahora la fecha permite introducir los años en formato
  de dos o cuatro cifras.
*/

var fecha_abreviada = /^\d{2}.?\w{3}.?(?:\d{2}|\d{4})$/
fecha_abreviada.test("25-feb-14")
fecha_abreviada.test("25-feb-2014")
fecha_abreviada.test("25-feb-204")

Banderas

Las banderas son opcionales, si se encuentran especificadas, las banderas pueden tener cualquier combinación de los siguientes valores:

Carácter Descripción
g Concordancia global
i Ignora si el texto está en mayúsculas y / o minúsculas
m Multilinea. Trata los caracteres de inicio / fin (^ / $) como si se estuviera trabajando con muchas líneas (cada línea está delimitada por \n \r).
var enunciado = "Javascript se puede utilizar con html. javascript es un lenguaje de programación"

/*
Reemplazar javascript por js donde aparezca en el texto. 
No importa si está en mayúsculas o minúsculas.  
*/

enunciado.replace(/javascript/ig, "js")
  
function test() {

  var js = /javascript/ig  
  var enunciado = "Javascript se puede utilizar con html. JAVASCRIPT es un lenguaje de programación"
  
  var elementos_encontrados = []
  
  while (existe =  js.exec(enunciado)) {
    elementos_encontrados.push(existe[0])
  }
  
  console.log(elementos_encontrados)
}

En español

Si se quieren utilizar caracteres propios del español hay que incluirlos directamente dentro del patrón.

/*
Verificación que los caracteres áéíóúüñ no son
tomados como caracteres alfabéticos. 
*/

var prueba =  /\w/

prueba.test("á")
prueba.test("é")
prueba.test("í")
prueba.test("ó")
prueba.test("ú")
prueba.test("ü")
prueba.test("ñ")


/*
Dependiendo de cómo esté definida nuestra 
expresión regular pueden obtenerse resultados imprevistos
*/

var validar =  /^[A-Za-z- ]{4,}$/      
// Ninguno es válido
validar.test("José")        
validar.test("Niño")        
validar.test("Pingüino")

/*
En este caso hay que incluir las letras
para que la expresión regular las tome en cuenta
*/

var validar2 =  /^[A-Za-z- áéíóúü]{4,}$/
// Ahora si son válidos
validar2.test("José ")
validar2.test("Niño")
validar2.test("Pingüino")

Otros idiomas

Aunque es posible agregar cada carácter que queramos comparar, esto no resulta muy útil si se utilizan otros alfabetos o se quiere dar soporte a varios idiomas al mismo tiempo.

En ese caso si conviene utilizar la librería xregexp y utilizar el plugin de unicode.

/*

Descargar xregex ( http://xregexp.com/ ) el plugin unicode base
(http://xregexp.com/plugins/ )  e incluirlos en el html como de costumbre. 

<script src="xregexp-min.js" type="text/javascript"></script>
<script src="unicode-base.js" type="text/javascript"></script>

*/

var saludo = XRegExp("[\\p{L}- ]$");
saludo.test("Hello Regex")
saludo.test("Здравствуйте регулярное выражение")
saludo.test("こんにちは、正規表現")
saludo.test("Bonjour expression régulière")
saludo.test("Hola expresión regular")