Cómo utilizar expresiones regulares en tu proyecto para manipular texto

Las Expresiones Regulares son muy útiles en tus proyectos cuando necesitas manipular texto en forma de control o archivo, ya sea HTML, SMTP, XML u otro formato. Las manipulaciones que puedes hacer con RegEx incluyen la capacidad de extraer cadenas (URLs de HTML) y reemplazar cadenas en un archivo (números de pedido en un archivo XML).

Índice de Contenido
  1. Expresiones Regulares intermedias
    1. Cuantificadores
    2. Agrupación
  2. Captura
  3. La clase Regex del framework .NET
    1. Regex.IsMatch
    2. Regex.Replace
  4. En el próximo artículo...

Expresiones Regulares intermedias

¿Qué más puedes hacer con las Expresiones Regulares en un nivel intermedio?

Cuantificadores

En mi último artículo, te mostré cómo se repetían ciertas secuencias de forma regular. Por ejemplo, para especificar un código postal, tenía que proporcionar la secuencia \d\d\d\d\d. Podrías esperar que haya una forma de establecer pautas cuantitativas para una expresión RegEx. Y estarías en lo cierto.

RegEx te permite especificar que una secuencia particular debe aparecer exactamente cinco veces al agregar {5} a su sintaxis. Por ejemplo, la expresión \d{5} especifica exactamente cinco dígitos numéricos. También puedes especificar una serie de al menos cuatro y no más de siete caracteres al agregar {4,7} a la secuencia.

De manera similar, la expresión [A-Z]{3,6} especifica de tres a seis instancias del conjunto de caracteres que consiste en letras mayúsculas. La expresión puede omitir uno de los dos designadores, lo que implica cero (0) en la posición anterior e ilimitado en la posición posterior. Si buscas un número de hasta seis dígitos de longitud, usarías {,6}. De manera similar, una palabra que tenga al menos cuatro caracteres de longitud se puede expresar como \w{4,}.

Además de la sintaxis genérica mencionada anteriormente, RegEx ofrece atajos para designar cuantificadores. El carácter de interrogación (?) se utiliza para designar cero o una coincidencia (equivalente a {0,1}). El carácter asterisco (*) se utiliza para designar cero o más coincidencias (equivalente a {0,}). Por último, el carácter de signo más (+) se utiliza para designar una o más coincidencias (equivalente a {1,}). El uso de estas secuencias puede hacer que tus expresiones sean más rápidas de escribir y más fáciles de leer.

Cómo utilizar diagramas de clases y secuencia para comunicar eficazmente en Java

Aquí tienes ejemplos de cómo podrías usar estas construcciones:

  • Un código postal simple: \d{5}
  • Un número de teléfono con o sin guiones: [2-9]\d{2}-?\d{3}-?\d{4}
  • Cualquier par de palabras separadas por un espacio: \w+ \w+
  • Una o dos palabras separadas por un espacio: \w* ?\w+

Agrupación

Hasta ahora, has visto cómo cuantificar secuencias de caracteres individuales dentro de una cadena. También sabes que una secuencia de literales (por ejemplo, joe) designa la subcadena en sí misma. Pero, ¿qué ocurre si quieres cuantificar la subcadena literal de caracteres? El lenguaje RegEx ofrece la construcción de agrupación con este propósito. Para designar un grupo, lo encierras en paréntesis.

Por ejemplo, (abc) es la secuencia abc dentro de la cadena. Por sí sola, no es diferente del literal abc. Sin embargo, cuando aplicas algunos de los cuantificadores, esta construcción se vuelve muy poderosa, especialmente cuando consideras que un grupo puede contener secuencias RegEx completas.

Anteriormente, escribí la expresión para un código postal simple como \d{5}. Sin embargo, los códigos postales también tienen una sección opcional que agrega un guión seguido de otros cuatro dígitos. La sección opcional se define fácilmente como -\d{4}. Pero, ¿cómo le indicas al motor de RegEx que es opcional? Podrías recordar que el signo de interrogación se utiliza para coincidir con cero o una vez.

Entonces, un código postal complejo se expresa como \d{5}(-\d{4})?. Para entenderlo, observa que la construcción de grupo se aplicó a la sección opcional y luego se designó como coincidencia cero o una vez mediante el cuantificador de interrogación. Puedes usar los otros cuantificadores para controlar las coincidencias dentro de la expresión. Por ejemplo, (abc){3} designa la secuencia abcabcabc.

Captura

La construcción de agrupación también tiene un significado secundario dentro del lenguaje RegEx. Crea un mecanismo para capturar una subcadena coincidente para su uso futuro, como extracción o reemplazo.

Guía para posicionar elementos en HTML con CSS

De forma predeterminada, cualquier grupo que designes dentro de una expresión es un grupo de captura. Los grupos se numeran de izquierda a derecha en el orden de paréntesis de apertura, incluso si los grupos están anidados. El grupo con índice 0 es un grupo especial que contiene la coincidencia completa, como si toda la expresión estuviera envuelta en un conjunto de paréntesis.

Veamos una expresión de grupos anidados para un número de teléfono: (([2-9]\d{2})-)?(\d{3})-(\d{4}). Observa que esta expresión contiene varios grupos, algunos anidados y otros no.

El primer conjunto de paréntesis captura los primeros tres dígitos del código de área, así como el guión que le sigue. Necesitamos poner este grupo aquí porque el código de área es opcional, como se designa con el signo de interrogación que sigue a su definición. Anidamos un segundo grupo para permitirnos extraer solo el código de área en sí mismo. Los dos conjuntos de paréntesis siguientes son más obvios en su captura. En este punto, puedes hacer referencia a varias secciones dentro de esta subcadena utilizando la notación de grupo.

No hay duda de que hacer un seguimiento de los grupos por número es una tarea bastante tediosa. Se complica aún más por el hecho de que se te obliga a designar un grupo (el primero) del que realmente no te importa mucho, solo para poder especificar que el código de área es opcional. RegEx aborda ambos problemas de manera bastante elegante utilizando grupos con nombres. Un grupo para un nombre se designa utilizando la sintaxis (?<nombre> … ).

Hay un caso especial que designa un grupo sin captura si el grupo comienza con ?: En el ejemplo anterior, podrías haber usado (?:([2-9]\d{2})-) para designar que el grupo de código de área y guión es un grupo sin captura. Esto ayuda a eliminar algunos de los grupos que están allí solo por razones de expresión y no por razones de reutilización.

Si aplicas ambas técnicas a la expresión de código postal, terminas con (?<completo>(?<base>\d{5})(?:-(?<ext>\d{4}))?). Ahora puedes hacer referencia al código postal completo, a la parte base y a la parte extendida individualmente por su nombre. La expresión también utiliza un grupo sin captura para ignorar el guión en la parte extendida. Un efecto secundario interesante de nombrar grupos es que todos los grupos con nombre se numeran después de todos los grupos sin nombre, lo que altera el orden de los paréntesis de apertura.

Dónde acuden los desarrolladores en busca de ayuda y soluciones

La clase Regex del framework .NET

Todavía hay mucho más en el lenguaje de Expresiones Regulares, pero es hora de cambiar el enfoque a algunos ejemplos de código. Para trabajar con Expresiones Regulares, el framework .NET ofrece la clase Regex en el espacio de nombres System.Text.RegularExpressions. (En este artículo, solo cubriré dos métodos sencillos de la clase, reservando algunos usos más complejos de esta clase para el próximo artículo de esta serie.)

Regex.IsMatch

La clase String del framework .NET ofrece el método IndexOf para determinar si una cadena contiene otra. Sin embargo, su uso está limitado intrínsecamente a una cadena literal. ¿Qué ocurre si deseas determinar si una cadena contiene otra cadena definida con una Expresión Regular? El framework .NET ofrece un método estático de la clase Regex con ese propósito.

Supongamos que deseas determinar si una cadena de entrada particular contiene un código postal. Ya sabes cómo escribir la expresión regular para un código postal. Todo lo que tienes que hacer es usar el método IsMatch para aplicar la prueba:
bool tieneCoincidencia = Regex.IsMatch(cadenaDeEntrada, @"\d{5}(-\d{4})?");

Vale la pena mencionar que el método IsMatch devolverá un valor verdadero si la coincidencia existe en cualquier lugar dentro de la subcadena. En general, sabes lo suficiente sobre la cadena de entrada como para no preocuparte por esto. Sin embargo, si necesitas especificar que toda la cadena debe coincidir con la expresión, puedes usar los modificadores ^ y $:
bool tieneCoincidencia = Regex.IsMatch(cadenaDeEntrada, @"^\d{5}(-\d{4})?$");

El lector avispado se preguntará cómo determinar si existen múltiples coincidencias y dónde aparecen en la cadena. Ambas características y más están disponibles en la clase Regex y se cubrirán en el próximo artículo de esta serie.

Regex.Replace

Al igual que el método analógico IndexOf de la clase String, la clase Regex también ofrece una forma de reemplazar subcadenas definidas como Expresiones Regulares. Supongamos que estás escribiendo un sencillo intérprete de HTML. Una de las características de HTML es que colapsa cualquier secuencia de espacios en blanco en la entrada a un solo espacio en la salida. Puedes usar la clase Regex para lograr lo mismo con el siguiente código:
string resultado = Regex.Replace(cadenaDeEntrada, @"\s+", " ");

Cómo pasar de constantes de tiempo de compilación a constantes en tiempo de ejecución

Este es un ejemplo muy sencillo, pero ilustra cómo puedes hacer cosas muy interesantes con el motor de RegEx. El método Replace es aún más potente en la medida que te permite hacer referencia a grupos de captura definidos en la expresión.

Hay dos formas sencillas de hacer referencia a grupos de captura en la cadena de reemplazo. Un signo de dólar seguido de cualquier número hace referencia a un grupo de captura por número. La secuencia $0 se refiere al grupo cero, que es el grupo especial para toda la cadena de entrada en este caso. La secuencia $2 se refiere al segundo grupo. Además, puedes especificar un grupo de captura con nombre usando la sintaxis ${nombre}.

Echemos un vistazo a dos ejemplos, ambos asumiendo que se llaman utilizando esta sintaxis:
string resultado = Regex.Replace(cadenaDeEntrada, patrón, reemplazo);
// asegurarse de que un número de teléfono tenga guiones
patrón = @"([2-9]\d{2})-?(\d{3})-?(\d{4})";
reemplazo = "$1-$2-$3";

// invertir el orden de los nombres y apellidos, ignorando el segundo nombre
patrón = @"(?<nombre>\w+) (?:\w+ )*(?<apellido>\w+)";
reemplazo = "*** ${apellido}, ${nombre} ***";

Ten en cuenta que solo los caracteres de referencia de grupos son especiales en la cadena de reemplazo. En el ejemplo anterior, los asteriscos se interpretan como caracteres literales dentro de la cadena. Sin embargo, si deseas colocar un signo de dólar literal en la cadena de reemplazo, puedes especificarlo con $$.

En el próximo artículo...

Ahora sabes cómo crear algunas Expresiones Regulares muy interesantes y usarlas en tu código. En el próximo artículo, completaré algunos de los elementos intermedios del lenguaje de Expresiones Regulares. También ampliaré la clase Regex y sus miembros. A lo largo de esta serie de artículos, ofreceré una referencia de sintaxis creciente para el lenguaje RegEx. Puedes enlazar a un resumen de todas las secuencias que he cubierto en esta serie.

Las funciones de manipulación de cadenas en JavaScript y cómo utilizarlas

En Newsmatic nos especializamos en tecnología de vanguardia, contamos con los artículos mas novedosos sobre Desarrollo, allí encontraras muchos artículos similares a Cómo utilizar expresiones regulares en tu proyecto para manipular texto , tenemos lo ultimo en tecnología 2023.

Artículos Relacionados

Subir

Utilizamos cookies para mejorar su experiencia de navegación, mostrarle anuncios o contenidos personalizados y analizar nuestro tráfico. Al hacer clic en “Aceptar todo” usted da su consentimiento a nuestro uso de las cookies.