Expresiones regulares
Una expresión regular define un patrón de búsqueda para cadenas de caracteres. En inglés se conoce como regular expression, regex o RegExp. Una expresión regular nos permite saber si el texto con el cual estamos trabajando tiene alguna coincidencia con el modelo que estamos definiendo con la expresión regular.
La búsqueda de patrones (pattern matching) está ideada para ahorrar tiempo y optimizar la comprobación de si una cadena de caracteres contienene o coincide con un patrón. El contenido de la cadena de carácteres puede coincidir con el patrón ninguna, una o varias veces.
Los patrones se buscan en el String de izquierda a derecha, es decir, desde la posición 0 hasta la última. Se va comprobando carácter a carácter si encaja con el patrón. Cuando se determina que un carácter cumple con el patrón, ese carácter no se vuelve a tener en cuenta en la comprobación.
En la mayoría de lenguajes de programación se proporcionan herramientas para poder usar las expresiones regulares.
Uso de las expresiones regulares
En programación, se usan para buscar y extraer determinadas secuencias de texto en una cadena de texto, para validar cadenas de texto, para realizar sustituciones de parte de un texto, etc.
Algunos ejemplos de uso reales son:
- Validar direcciones de email.
- Validar números de teléfono.
- Validar contraseñas seguras.
- Comprobar formato de fechas.
- Detectar números de tarjeta de crédito.
- Extraer URLs de un texto.
- Validar identificadores como el DNI.
- Limpiar o transformar texto.
- Buscar y reemplazar patrones en logs o documentos.
- Tokenizar texto en análisis de lenguaje natural.
Uso de expresiones regulares con String
La clase String implementa varios métodos que nos permiten realizar una serie de acciones con las cadenas de texto.
Algunos métodos relacionados con la búsqueda son:
String str = "The String class represents character strings.";
// Obtener el carácter en un índice concreto.
str.charAt(1); // 'h'
// Obtener el índice donde se almacena la primera ocurrencia de un cáracter.
str.indexOf('S'); // 4
// Comprobar si una cadena de texto está contenida en otra.
str.contains("class"); // true
Algunos métodos relacionados con la manipulación de cadenas de texto son:
String str = "The String class represents character strings.";
// Reemplazar carácteres.
str.replace('a', 'A'); // "The String clAss represents chArActer strings."
// Reemplazar fragmentos de la cadena de texto por otros.
str.replace("re", "RE"); // "The String class REpREsents character strings."
// Convertir todos los carácteres a mayúsculas.
str.toUpperCase(); // "THE STRING CLASS REPRESENTS CHARACTER STRINGS."
// Convertir todos los carácteres a minúsculas.
str.toLowerCase(); // "the string class represents character strings."
Los métodos anteriores nos permiten buscar y/o manipular fragmentos concretos de una cadena de texto. Si queremos realizar búsquedas y/o manipulaciones de ciertos fragmentos con alguna variación, debemos realizar una búsqueda y/o maniuplación para cada una de las variaciones.
Por ejemplo, si deseamos buscar si hay alguna r seguida de una vocal minúscula (ra, re, ri, ro y ru ) tendríamos que hacer lo siguiente:
String str = "The String class represents character strings.";
boolean ra = str.contains("ra"); // true
boolean re = str.contains("re"); // true
boolean ri = str.contains("ri"); // true
boolean ro = str.contains("ro"); // false
boolean ru = str.contains("ru"); // false
if(ra || re || ri || ro || ru) {
System.out.println("Coincidencia encontrada."); // Muestra el mensaje.
}
Si deseamos agregar más términos de búsqueda, deberíamos agregar más llamadas al método contains(). Es posible que, si tenemos muchos términos para buscar, esta forma de abordar el problema se vuelva inviable.
Debemos buscar otra solución. Una forma podría ser la siguiente:
String str = "The String class represents character strings.";
boolean match = str.matches(".*r[aeiou].*"); // true
if(match) {
System.out.println("Coincidencia encontrada."); // Muestra el mensaje.
}
En el último fragmento de código, se agrupan los términos de búsqueda "ra", "re", "ri", "ro" y "ru" en una única expresión: ".*r[aeiou].*". Esta última expresión, la cual puede parecer que no tiene sentido, define un patrón de búsqueda y se denomina expresión regular.