Expresiones regulares, ahora en modo fácil!

Lecherito

Ejercicios

Bueeeno, ahora que hemos visto lo básico de las expresiones regulares, va siendo hora de practicarlas con algunos ejercicios simples! Para hacer estos ejercicios, se usará la página web www.regex101.com y con la opción de permalink me mandáis un PM con la respuesta, los ejercicios se hacen desde el principio, no me vale que me hagáis el ejercicio 20 por que los demás son muy fáciles, tendré un post de hasta qué ejercicio ha hecho cada uno.

Para el PM: El enunciado de cada ejercicio será la seccion (Caracteres especiales...etc), y el número de ejercicio.

  • 1- Has de encontrar todas las A del siguiente texto: ahora voy a nAdar con MARIA.

  • 2- Cambia todas las vocales de esta frase por la vocal e: Mi moto alpina de repente.

  • 3- Haz que la siguiente expresión regular sea case insensitive solo y exclusivamente en la palabra hola: /hola amigo/

  • 1- Construye una expresión regular que encuentre el siguiente texto: ·"$("!$·/\\

  • 2- Construye una expresion regular que encuentre todos los números de un texto, como por ejemplo: 83 psf2 463p j6 832p42863

  • 3- Queremos encontrar todas las letras mayúsculas excepto las vocales del siguiente texto: A38bBv801nWZZ

  • 1- Queremos encontrar la palabra: hola en cualquier lugar de un texto, tantas veces como sea.

  • 2- Queremos encontrar las lineas de un texto que empiezan por N y terminan por s. (El punto es literal)

  • 3- Queremos buscar los números que están en una posición par de la cadena, por ejemplo: a3m9f33n3n3n encontraríamos 3, 9, 3.

  • 1- Usa las "backreference" para meter en \1 el valor de cada 2 palabras de un texto cualquiera. (Modificador global)

  • 2- Queremos sacar las palabras hola amigo de un texto cualquiera, pero queremos que amigo sea CASE INSENSITIVE (la palabra hola ha de ir siempre en minúscula). A su vez, lo sustituiremos todo por Hello Friend (en todas las ocurrencias del texto, el texto puede inventarselo).

  • 3- Queremos reemplazar de un texto la palabra texto, seguida de las palabras subrayado, negrito por ::texto subrayado:: (lo que es añadirle :: al principio y al final), como lo harías?

Lecherito

Seguimiento ejercicios

oip:

spoiler

iAtlas:

spoiler

aNuBiS:

spoiler
aNuBiS

Como tengo que estudiar (XDD) me estoy entreteniendo en pasar el tutorial a Markdown como sugirió #21, pero tiene problemas con los acentos y los "¿". Para el resto de cosas es bastante sencillo siguiendo la guía de http://daringfireball.net/projects/markdown/syntax

Lo dejo en pastebin para que no haya rollos con el formato, por si alguien quiere continuarlo: http://pastebin.com/Qbwrk4Gb#

1 respuesta
Lecherito

#33 Yo la verdad es que me da una pereza enorme, bastante tengo con escribirlo xDD

A ver si más gente se anima con los ejercicios!

Lecherito

5- Grupos

Un grupo es un conjunto de caracteres (que puede incluir clases de caracteres, alternación etc), pero en global es un grupo. Realmente, toda una expresión regular en si ya es un grupo, por ejemplo esta expresión /abc/ es internamente un grupo ya que la a, si no hay b, no hace nada, al igual que la c no la encontrará si no hay ab antes. Es como un todo o nada, el grupo ha de encontrarlo entero, si no, dirá/hará como que no ha encontrado nada.

Los grupos tienen otras propiedades:

  • 1- La primera propiedad es que podemos usar más tarde el valor de ese grupo. Esto significa que si se tiene un grupo con la primera palabra de una frase, esa palabra se podrá usar después en el tiempo en tu programa, esto se hace en cada lenguaje de programación de una manera así que eso o preguntas por el hilo, o te buscas las castañas, aunque intentaré poner ejemplos específicos de unos cuantos lenguajes de programación.

  • 2- Poder usar esos grupos más tarde en la misma expresión regular, para no escribir dos veces lo mismo, también se puede usar como recursividad pero eso es más avanzado y se verá más adelante, no hace falta entenderlo ahora mismo.

  • 3- Poder usar esos grupos en la sustitución, en los primeros ejercicios hay uno de sustitución, pero en esa sustitución se puede meter el valor que había en el grupo 1 por ejemplo. Si tienes el grupo /(abc)/ la cadena abc es parte del grupo 1 y como tal, se puede usar más tarde en la sustitución usando \1, \1 lo que le dice a la sustitución es: pon aquí lo que contenga el grupo 1. Tan facil como eso!

IMPORTANTE DING DING DING: los grupos se numeran de izquierda a derecha por orden de apertura de paréntesis.

Como ya dijimos en los caracteres especiales, un grupo se define por que está entre paréntesis b[/b], así que habrá especies de subrupos dentro del grupo general de la expresión regular, por ejemplo /(abc)/ sería lo mismo que /abc/ pero lo bueno de los grupos es que nos dan otro tipo de posibilidades por ejemplo ponerle cuantificadores al grupo, ponerle algún modificador solamente a ese grupo, alternación dentro de ese grupo (así como otro tipo de cosas que ya veremos).

Hay casi una posibilidad infinita de "operaciones" con los grupos (no son realmente operaciones), pero se le pueden meter cuantificadores, modificadores, alternación, lookaround etc. Los lookaround son realmente importantes así que tendrán su propia sección más adelante, ahora explicaré un poquito sobre las otras opciones.

  • Cuantificadores en grupos: Cuando tenemos por ejemplo en mysql una sentencia del tipo select a,b,c from d; y queremos sacar de ahí a,b,c que son las columnas y queremos sus nombres. Realmente, podemos usar algo del tipo literalmente /a,b,c/ pero es que resulta que esos nombres tienen una longitud variable al igual que sus letras pueden cambiar! Qué hacer con esto, un grupo, realmente el a,b,c se podría ver como un grupo de: unas letras, separadas por comas donde hay como mínimo una tabla y puede haber muchas. Y cómo traducir eso a una expresión regular? /[a-z]+(,[a-z]+)+/ aunque realmente esta expresión regular parece muy complicada, es sencilla si habéis estado leyendo donde: [a-z]+ significa una letra de la a a la z una o más veces. cmd+[/cmd] esto significa (lo que está en entre paréntesis es un grupo), una COMA literal, y como anteriormente una letra repetida una o más veces, y ahora viene lo bueno, EL GRUPO SE PUEDE REPETIR 1 O MÁS VECES. Que es aquí donde empieza la utilidad de los grupos. (Ejemplo)

  • Alternancia en grupos: Al igual que dije hace tiempo en el capítulo de los caracteres especiales, existe alternancia en grupos. ¿Qué es la alternacia en grupos?, pues dentro de un grupo puedes decir que puede haber A, o puede haber B, cómo hacer esto?, un ejemplo al igual que lo puse antes /(A|B)/, ultrasencillo! (Al igual que en muchos lenguajes de programación, el carácter | significa OR). Dentro de cada caso de la alternancia, puedes meter incluso OTRA EXPRESIÓN REGULAR, no hace falta que sea tan sencillo como este ejemplo.

  • Grupos que no capturan: Por defecto, los grupos capturan. Los grupos, como dije en el punto 1 de las propiedades de los grupos capturan y se puede usar el valor más tarde. Esto causa que tenga que usar una variable y guardar el valor! Si realmente no necesitas usar ese valor más adelante pero necesitas que siga actuando como grupo, hay grupos que simplemente no guardan el valor (es un aumento de eficiencia). Simplemente al inicio del grupo, hay que poner ?:, por ejemplo un grupo que no captura: (?:hola, aqui no capturo). Es tan simple como esto, y además supone un aumento en la eficiencia de las expresiones regulares, que como ya veremos, en los tipos de expresiones regulares NFA (non deterministic) la eficiencia será muy importante.

  • Grupos atómicos: Los grupos atómicos (atomic grouping), son un tipo especial de grupos que cuando encuentran algo, es suyo y de nadie más. Esto significa (lo podeis ver bien con este ejemplo, este otro es con una alternación normal ejemplo), que como en el primer ejemplo, empieza encontrando la a, luego puede encontrar o bien b o bc, en un grupo atómico, al principio encontrará b, por la propiedad de la atomicidad del grupo, no habrá posibilidad de backtrack así que ahora, despues de encontrar algo, sale de toda la alternancia, esto es, una vez que encuentra algo, terminará esa alternancia. En un grupo normal, el motor de la expresión regular, intentará por todos los medios hacer un match general antes que su match, (es como si tienes 10 monedas, le das 5 a tu amigo para tener los 2 algo de dinero, como sacrificarte por el grupo). En el segundo ejemplo ya habéis visto que encuentra un match, ya que primero encuentra la b, pero como de esa manera no hay match general, intenta la bc y ahora que hay match y no hay más opciones, termina. RESUMEN: Un grupo atómico es un grupo que no da derecho a backtrack, cuando encuentra algo es suyo y sale del grupo, y no hay posibilidad de volver atrás.

  • Grupos con nombre: Sabéis que los grupos, cuando vas a devolver su valor, se numeran de izquierda a derecha según la apertura de los paréntesis. Pero hay una pequeña excepción, los grupos que tienen nombre. A un grupo tu le puedes dar un nombre, y más tarde devolver su valor con algo del tipo objeto.group("valor" ) ; si tuvieramos un grupo tal que cmd[/cmd]. La sintaxis es cmd[/cmd]. Es bastante sencilla ya que sigue la dinámica de las otras sintaxis, empieza con ? y luego otro carácter que es lo que realmente delimita qué tipo de grupo es.

1
th3vil

#1 vaya currada macho jajaja to favs

Lecherito

4.1- Listado de abreviaturas en las expresiones regulares

Como ya dije anteriormente con el carácter \ se escapan caracteres, pero como también dije, también es posible darle un significado especial a otros caracteres, por ejemplo \d es una abreviatura de [0-9].

  • \d: Los dígitos, una abreviatura de [0-9]

  • \D: La negación de \d

  • \w: Las "palabras", una abreviatura de [a-zA-Z0-9_] (nótese la _)

  • \W: La negación de \w

  • \t: Un tabulador.

  • \r: Carriage return, es como la nueva línea en linux.

  • \n: Carácter de una nueva linea.

  • \s: Los whitespaces, una abreviatura de [ \t\n\r]

  • \uXXXX: Para caracteres UNICODE donde XXXX son los números del carácter unicode.

  • \b: Caracter de word boundary. La forma larga es: cmd[/cmd]

  • \B: La negación de \b

Los word boundaries, es un anchor (no consume el siguiente carácter en la expresión), pero un anchor un tanto especial, que lo que hace es delimitar las palabras. La definición de límites de las palabras no es ni más ni menos que \W, una palabra está delimitada por \w, como dije más arriba (\word). Por ejemplo \bword\b, en la cadena unwordy no lo encontrará, pero en la cadena hi, I'm a word! si la encontrará, como se ve en el siguiente ejemplo.

Como vemos, no tiene ningún misterio, y es bastante útil para no encontrar cosas que están en medio de otras palabras.

iAtlas

Con cada capítulo aprendo algo nuevo. No sabía para que servía el \b. En su caso he estado utilizando ^(.*\W)?word(\W.*)?$

1 respuesta
Lecherito

#38 Pues ya puedes simplificarlo con \bword\b xDD

Lecherito

Añadidos 3 ejercicios de anchos, y ya mismito pongo otros 3 de grupos.

iAtlas

He podido hacer los dos primeros de "anchor", pero los otros por mucho que he probado no me han salido. Mañana les echo otro ojo.

1 respuesta
Lecherito

#41 Para dudas ya sabes (el 3º de anchors diría que es algo difícil por si no te quieres comer mucho la cabeza ahora)

1 respuesta
LOc0

#42

¿Se permiten "null matches" en ese ejercicio?

Salu2 ;)

1 respuesta
Lecherito

#43 ¿A qué te refieres como "null matches"?

1 respuesta
Lecherito

Si os habéis leido ya lo de los grupos, he añadido otros 2 tipos de grupos, los que no capturan (non capturing groups) y los grupos atómicos (atomic grouping).

También añadidos los grupos con nombre!

Son interesantes! especialmente el segundo.

Lecherito

5.1- Lookarounds

Los lookaround son una especie de condicionales para la expresión regular. Son una especie de mini expresión regular dentro de esa, que NO modifica el puntero interno de la expresión, por lo tanto un pequeño ejemplo, queremos encontrar todas las A pero a esa A no le puede seguir una B. Este es el tipo de cuestiones que solucionan las lookaround, de hecho, el ejemplo sería algo del tipo ejemplo la expresión regular A(?!B) significa literalmente lo que el texto de antes, una A que no le siga una B, y con el modificador global encontramos tooodas las que haya.

Hay cuatro tipos de lookarounds, puedes mirar hacia adelante y hacia atrás, y positiva y negativamente.

  • Lookbehind

  • Negative lookbehind

  • Lookahead

  • Negative lookahead

Lookahead significa literalmente mira hacia adelante. El constructor de lookahead es cmd[/cmd], dentro de expresión puede haber literalmente una expresión regular compleja, y, al contrario que con los lookbehind no tienen una longitud fija. Por lo tanto se pueden usar del tipo cmd[/cmd] que viene a significar que ha de tener una B en algún lugar de la expresión (aunque no está del todo completa). Son muy útiles ya que no avanzan posición en el cursor de la expresión regular por lo tanto son unos condicionales.

Una vez que ya sabemos que el puntero de la expresión regular (a qué carácter apunta) no se mueve con los lookaround es muy fácil usarlos ya que lo único que necesitas es saber cual es su sintaxis. La sintaxis es cmd[/cmd], simplemente ha de empezar con ?!.

Lookbehind, tiene unas pequeñas limitaciones (en JGSofg o .NET no las tiene) y es que debido al backtracking que hace se hace prácticamente eterno, por lo tanto no dejan que sea de longitud VARIABLE, por lo que no dejan cuantificadores. La sintaxis es cmd[/cmd].

Es prácticamente lo mismo, pero negándolo, y la sintaxis es cmd[/cmd]. No hay que hablar mucho sobre esto, lo más dificil es entender cómo funcionan los lookaround.

LOc0

#44

A un zero-width match. De todas formas, ¿en los ejercicios de anchors se pueden usar cosas que todavía no se han explicado en el manual?

Salu2 ;)

Lecherito

Fuck joder, luego pondré aquí el siguiente capítulo que se me ha ido.

DarkSoldier

pues nada, a leer se ha dicho, +1 lecherito

Lecherito

Nadie por aquí? :-c

Mañana en clase me pondré y escribiré unos cuantos ejemplos!

1 mes después
k1k0_o

Añado un recurso más que ví el otro día por Twitter y la verdad es que es un MUST BE!

http://www.debuggex.com

3 1 respuesta
Lecherito

#51 Hostias que OP, la verdad es que está bastante bien ya que realmente puedes ver por donde va la expresión +1

27 días después
iAtlas

He encontrado esta página que ofrece, entre varios lenguajes de programación, un libro con varios capitulos para comenzar con regex.

http://regex.learncodethehardway.org/book/

No lo he mirado en profundidad, pero he visto que no está completo aún. De todas maneras, los primeros capítulos sí que están y pienso que también puede venir bien para comenzar.

3 meses después
iAtlas

Resucito el hilo para poner esta página que consiste en resolver algo parecido a crucigramas con expresiones regulares:

http://regexcrossword.com/

Tiene un tutorial y varios niveles de dificultad, a ver hasta donde llegais :)

1 1 respuesta
Lecherito

#54 Está curioso, la verdad es que me va a ser un entretenimiento, estoy en Moscú y he de esperar hasta las 12 hasta que salga el avión

1 mes después
k1k0_o

Sitio sencillo y molón para probar cosas rápido:

http://leaverou.github.io/regexplained/

1 respuesta
Lecherito

#56 Me sigue gustando más regex101.com, te colorea los grupos etc etc.

1 mes después
Lecherito

Se me olvidó decirlo, www.regex101.com ha implementado un debugger de las PCRE, (además de soportar regex en Javascript y Python)

Muy muy útil ya que te pone por donde va la regex y qué está haciendo match, si hace backtrack o no etc etc!

corono

Qué descubrimiento!! Gran aporte crack.

6 meses después
k1k0_o

Un pequeño gran aporte visto en Hacker News:

http://www.regexr.com/

Usuarios habituales

  • Lecherito
  • k1k0_o
  • iAtlas
  • DarkSoldier
  • LOc0
  • aNuBiS
  • eisenfaust