Aprendizaje de expresiones regulares [cerrado]

Aug 07 2008

Realmente no entiendo las expresiones regulares. ¿Me las puede explicar de una manera fácil de seguir? Si hay herramientas o libros en línea, ¿podría vincularlos también?

Respuestas

802 GregBacon May 03 2010 at 23:09

La parte más importante son los conceptos. Una vez que comprenda cómo funcionan los bloques de construcción, las diferencias en la sintaxis equivalen a poco más que dialectos suaves. Una capa sobre la sintaxis de su motor de expresiones regulares es la sintaxis del lenguaje de programación que está utilizando. Los lenguajes como Perl eliminan la mayor parte de esta complicación, pero tendrá que tener en cuenta otras consideraciones si utiliza expresiones regulares en un programa C.

Si piensa en las expresiones regulares como bloques de construcción que puede mezclar y combinar a su gusto, le ayudará a aprender a escribir y depurar sus propios patrones, pero también a comprender los patrones escritos por otros.

Empiece simple

Conceptualmente, las expresiones regulares más simples son caracteres literales. El patrón Ncoincide con el carácter 'N'.

Las expresiones regulares una junto a la otra coinciden con las secuencias. Por ejemplo, el patrón Nickcoincide con la secuencia 'N' seguida de 'i' seguida de 'c' seguida de 'k'.

Si alguna vez ha usado grepen Unix, aunque solo sea para buscar cadenas de aspecto ordinario, ¡ya ha estado usando expresiones regulares! (La reen se greprefiere a expresiones regulares).

Orden del menú

Agregando solo un poco de complejidad, puede hacer coincidir 'Nick' o 'nick' con el patrón [Nn]ick. La parte entre corchetes es una clase de caracteres , lo que significa que coincide exactamente con uno de los caracteres incluidos. También puede usar rangos en clases de caracteres, por lo que [a-c]coincide con 'a', 'b' o 'c'.

El patrón .es especial: en lugar de coincidir solo con un punto literal, coincide con cualquier carácter . Es lo mismo conceptualmente que la clase de personajes realmente grande [-.?+%$A-Za-z0-9...].

Piense en las clases de personajes como menús: elija solo uno.

Atajos útiles

El uso .puede ahorrarle mucho escribir y existen otros atajos para patrones comunes. Digamos que desea hacer coincidir un dígito: es una forma de escribir [0-9]. Los dígitos son un objetivo de coincidencia frecuente, por lo que podría utilizar el acceso directo \d. Otros son \s(espacios en blanco) y \w(caracteres de palabra: alfanuméricos o subrayado).

Las variantes en mayúsculas son sus complementos, por lo que \Scoincide con cualquier carácter que no sea un espacio en blanco, por ejemplo.

Una vez no es suficiente

A partir de ahí, puede repetir partes de su patrón con cuantificadores . Por ejemplo, el patrón ab?ccoincide con 'abc' o 'ac' porque el ?cuantificador hace que el subpatrón que modifica sea opcional. Otros cuantificadores son

  • * (cero o más veces)
  • + (una o más veces)
  • {n}(exactamente n veces)
  • {n,}(al menos n veces)
  • {n,m}(al menos n veces pero no más de m veces)

Al juntar algunos de estos bloques, el patrón [Nn]*ickcoincide con todos los

  • ick
  • Mella
  • mella
  • Nnick
  • nNick
  • nnick
  • (etcétera)

El primer partido demuestra una lección importante: ¡ *siempre tiene éxito! Cualquier patrón puede coincidir cero veces.

Algunos otros ejemplos útiles:

  • [0-9]+(y su equivalente \d+) coincide con cualquier número entero no negativo
  • \d{4}-\d{2}-\d{2} coincide con fechas formateadas como 2019-01-01

Agrupamiento

Un cuantificador modifica el patrón a su izquierda inmediata. Es de esperar 0abc+0que coincida con '0abc0', '0abcabc0', etc., pero el patrón inmediatamente a la izquierda del cuantificador positivo es c. Esto significa que 0abc+0coincide con '0abc0', '0abcc0', '0abccc0', etc.

Para hacer coincidir una o más secuencias de 'abc' con ceros en los extremos, use 0(abc)+0. Los paréntesis denotan un subpatrón que se puede cuantificar como una unidad. También es común que los motores de expresiones regulares guarden o "capturen" la parte del texto de entrada que coincide con un grupo entre paréntesis. Extraer bits de esta manera es mucho más flexible y menos propenso a errores que contar índices y substr.

Alternancia

Anteriormente, vimos una forma de hacer coincidir 'Nick' o 'nick'. Otro es con alternancia como en Nick|nick. Recuerde que la alternancia incluye todo a su izquierda y todo a su derecha. Utilizar agrupación paréntesis, a limitar el alcance de |, por ejemplo , (Nick|nick).

Para otro ejemplo, podría escribir de manera equivalente [a-c]como a|b|c, pero es probable que esto sea subóptimo porque muchas implementaciones asumen que las alternativas tendrán longitudes mayores que 1.

Escapando

Aunque algunos personajes coinciden con ellos mismos, otros tienen significados especiales. El patrón \d+no coincide con la barra invertida seguida de una D minúscula seguida de un signo más: para obtener eso, usaríamos \\d\+. Una barra invertida elimina el significado especial del siguiente carácter.

Codicia

Los cuantificadores de expresión regular son codiciosos. Esto significa que coinciden con la mayor cantidad de texto posible y, al mismo tiempo, permiten que todo el patrón coincida correctamente.

Por ejemplo, digamos que la entrada es

"Hola", dijo ella, "¿Cómo estás?"

Puede esperar ".+"que coincida solo con "Hola" y luego se sorprenderá cuando vea que coincide con "Hola" hasta "¿usted?".

Para cambiar de codicioso a lo que podría considerar cauteloso, agregue un extra ?al cuantificador. Ahora comprende cómo funciona \((.+?)\)el ejemplo de su pregunta. Coincide con la secuencia de un paréntesis izquierdo literal, seguido de uno o más caracteres y terminado con un paréntesis derecho.

Si su entrada es '(123) (456)', entonces la primera captura será '123'. Los cuantificadores no codiciosos quieren permitir que el resto del patrón comience a coincidir lo antes posible.

(En cuanto a su confusión, no conozco ningún dialecto de expresión regular en el que ((.+?))se haga lo mismo. Sospecho que algo se perdió en la transmisión en algún punto del camino).

Anclas

Utilice el patrón especial ^para que coincida solo al principio de su entrada y $para que coincida solo al final. Hacer "sujetalibros" con tus patrones en los que dices: "Sé lo que hay en la parte delantera y trasera, pero dame todo lo que hay entre ambos" es una técnica útil.

Di que quieres hacer coincidir los comentarios del formulario.

-- This is a comment --

escribirías ^--\s+(.+)\s+--$.

Construye tu propio

Las expresiones regulares son recursivas, por lo que ahora que comprende estas reglas básicas, puede combinarlas como desee.

Herramientas para escribir y depurar expresiones regulares:

  • RegExr (para JavaScript)
  • Perl: YAPE: Regex Explicar
  • Entrenador Regex (motor respaldado por CL-PPCRE )
  • RegexPal (para JavaScript)
  • Probador en línea de expresiones regulares
  • Buddy Regex
  • Regex 101 (para PCRE, JavaScript, Python, Golang)
  • RegExp visual
  • Expresso (para .NET)
  • Rubular (para Ruby)
  • Biblioteca de expresiones regulares (expresiones regulares predefinidas para escenarios comunes)
  • Txt2RE
  • Probador de expresiones regulares (para JavaScript)
  • Regex Storm (para .NET)
  • Debuggex (probador y ayudante de expresiones regulares visuales)

Libros

  • Dominando las expresiones regulares , la 2ª edición y la 3ª edición .
  • Hoja de referencia de expresiones regulares
  • Libro de cocina Regex
  • Aprenda a usar expresiones regulares

Recursos gratuitos

  • RegexOne: aprenda con ejercicios sencillos e interactivos.
  • Expresiones regulares: todo lo que debe saber (serie PDF)
  • Resumen de sintaxis de expresiones regulares
  • Cómo funcionan las expresiones regulares

Nota

†: La afirmación anterior que .coincide con cualquier carácter es una simplificación con fines pedagógicos que no es estrictamente cierta. El punto coincide con cualquier carácter excepto la nueva línea, "\n"pero en la práctica rara vez se espera que un patrón .+cruce un límite de nueva línea. Las expresiones regulares de Perl tienen un /sinterruptor y Java Pattern.DOTALL, por ejemplo, para hacer .coincidir cualquier carácter. Para los idiomas que no tienen esta característica, puede usar algo como [\s\S]para hacer coincidir "cualquier espacio en blanco o cualquier espacio que no sea en blanco", en otras palabras, cualquier cosa.