Expresiones regulares: unas buenas amigas

Os queremos presentar una enorme ayuda para cualquier tarea relacionada con texto en formato electrónico. Son fáciles de utilizar y nosotros las usamos continuamente: corpus, bases de datos, webs (en php), eBooks… Puede resultar obvio para algunos, pero yo las empecé a utilizar hace no demasiado y ahora son vitales.

Las expresiones regulares son formas genéricas de representar texto: desde caracteres individuales hasta párrafos completos. Un ejemplo sencillo de expresión regular son los caracteres * y ? que se pueden utilizar en muchos corpus o web. Nosotros mismos, en nuestra guía de citas famosas Casa de Citas permitimos búsquedas con *; también lo hace el Corpus del español, de Mark Davies o el Molino de Ideas en su corpus de prensa Hemero, donde se explica perfectamente:

Otra herramienta lingüística que permite utilizar caracteres especiales es BuFón (Buscador de patrones fonológicos), del CSIC, que, como podéis ver en la imagen, permite seleccionar finales de palabra, de sílaba (y muchísimo más si leemos la Guía de referencia rápida):

Las expresiones regulares se pueden utilizar en decenas de lenguajes y programas. Para aprender a utilizarlas vamos a realizar un caso de uso muy sencillo y muy útil que nosotros utilizamos en nuestra conversión de eBooks para la colección Clásicos Hispánicos (distribuida por Musa a las 9). Imaginemos que tenemos un texto (ya en un archivo tipo txt) que queremos pasar a HTML (para un post, una web, un eBook…). En nuestro caso vamos a partir del capítulo 4 de El Buscón, de Quevedo, en nuestra maravillosa edición preparada por Pablo Jauralde. Necesitaríamos colocar en cada línea las etiquetas <p> y </p> que señalan que empieza y termina un párrafo. Esto no puede resultar problemático si tienes una decena de párrafos, pero si, como ocurre en el caso de El Buscón, tienes más de mil líneas de texto, puede ser bastante tedioso. Abrimos el archivo en un editor de texto, por ejemplo Notepad++ (que os lo podéis descargar gratis en este enlace):

Una vez tenemos el archivo de texto abierto, abriremos el menú Reemplazar, al que accedemos apretando Control+H o clickando en Buscar>Reemplazar.

Los elementos más importantes de esa ventana son las dos cajas de texto “Buscar” y “Reemplazar con”:

La parte de Buscar funciona de la misma manera que la búsqueda en un archivo Word en nuestro navegador, solo que con esta ventana no solo podemos pedirle que nos encuentre algo, sino que lo reemplace por otra cosa. Un error que cometen bastantes personas al escribir es escribir un punto después de un símbolo de interrogación: “¿Sabes de lo que te hablo?.” Eso es un error y gracias a este menú de Buscar y reemplazar podemos asegurarnos de que en nuestro texto no haya nada de eso:

Como os podíais imaginar, en nuestro texto no había ninguno de estos casos.

Para utilizar las expresiones regulares vamos a utilizar este menú clickando la opción de “Expresión regular” que aparece abajo a la izquierda:

Una vez hemos clickado esto, el menú de Buscar y Reemplazar nos permitirá utilizar expresiones regulares. En nuestro caso, lo que queremos decirle al programa es algo así: “quiero que pongas una etiqueta <p> al comienzo de cada línea/párrafo; y también quiero que pongas una etiqueta </p> al final de cada línea/párrafo”. Como se explica en la wikipedia o en esta web específica sobre expresiones regulares (webs en las que podéis ampliar información), para señalar el comienzo de línea se utiliza el caracter ^; para señalar el final, el caractere $.


Entre el comienzo y el final de la línea puede haber la cualquier cantidad de caracteres.

  • Cualquier caracter se suele representar con el punto: .
  • Y cualquier cantidad (desde 0 hasta n) se suele representar con el asterisco: *

Por lo tanto “una línea desde su comienzo hasta el final con cualquier cosa en el medio” se dice en expresión regular ^.*$

¿Con esto tendríamos suficiente para poner las etiquetas <p></p>? Vamos a probarlo. Rellenamos las cajas de texto como podéis ver, clickamos en “Reemplazar todo” y el resultado es:

Catastrófico: hemos borrado todo el texto. Lo primero es clickar en “Deshacer”. Lo que ha ocurrido es que le hemos dicho “Busca cualquier línea que tenga cualquier cantidad de caracteres entre su principio y su fin, y eso lo sustituyes por ‘<p></p>’ “. Y evidentemente es lo que ha ocurrido. Pero en realidad no queremos eso, queremos que el texto que hay entre el principio y el final de cada línea lo mantenga y que a eso le añada las etiquetas <p></p>. Eso se puede hacer de dos maneras.

Una manera sería decirle: busca el comienzo de cualquier línea y ponle la etiqueta <p>, es decir: busca “^”, reemplaza por “<p>”:

Después se realizaría el cambio de: busca “$”, reemplaza por “</p>” y ya tendríamos nuestro textos con las etiquetas de párrafo.

Otra manera de realizarlo de una sola tacada sería mejorando la búsqueda de ^.*$. Lo que tenemos que conseguir es que el programa “recuerde” el texto y que lo vuelva a poner al reemplazarlo. Para señalarle al programa que tiene que guardar un dato se utilizan los paréntesis: ^(.*)$ Con esa búsqueda lo que le decimos al programa es: “Busca cualquier cantidad de caracteres entre el principio y el final de una línea y guárdate ese texto porque lo vamos a necesitar”.

Para reponer ese texto en la caja de “Reemplazar con” se utiliza la fórmula \número. En nuestro caso, como todo el texto de cada línea lo hemos guardado en un solo paréntesis, solo necesitaremos utilizar \1

Es decir, que la fórmula queda de la siguiente manera: busca “^(.*)$”, reemplaza por “<p>\1</p>”.

Al clickar en “Reemplazar todo”, conseguiremos con un solo click el resultado que queremos:

Grosso modo. Porque en realidad <p></p> (línea 3) es un error. Para que estos errores no ocurran, podemos modificar la búsqueda; en ella ya no utilizaremos el caracter * (que recordemos significa cualquier cantidad de caracteres, incluido NINGUNO, como ocurre en la línea 3) sino que utilizaremos el caracter + (cualquier cantidad de caracteres, como mínimo 1). Por lo que la fórmula quedaría: busca “^(.+)$”, reemplaza por “<p>\1</p>”. Al ejecutarlo, el resultado es:

Lindo. Todas las etiquetas de párrafo colocadas de manera correcta de un solo golpe.

Esperamos que os sea útil y que probéis la enorme capacidad que tienen las expresiones regulares. Y a los que ya las utilizan, contados: ¿Cuál es el trabajo que os suelen aligerar las expresiones regulares?

12 Responses to “Expresiones regulares: unas buenas amigas”

  1. Anonimo

    Gracias por este estudio es muy valioso, tengo una Expresion que no he podido realizar lo que quiero hacer es lo siguientes (soy nuevo en expresiones regulares).

    [uno "abcd123"]
    espacio en blanco
    {fdfdfn1sfk24
    jnvjndvnmvfvnvjjnfv
    njnjnjnnnnjjn
    }
    espacio en blanco

    Entre los espacios en blanco quiero incertar diferentes lineas no siempre son 3 lineas hay veces que son mas lineas.

    Gracias por la ayuda

    Responder
    • José Calvo

      Perdona anónimo, pero la verdad es que no entiendo exactamente a lo que te refieres. Si quieres intenta explicarlo más claro y te ayudo ;)
      Un saludo,
      José

      Responder
  2. Laramjo

    Hola como puedo hacer las siguientes cosas:

    1. ordenar un texto que tengo de la siguiente manera:

    1. aaaaaaaaaa 2. bbbbbbbbbbb 3. cccccccccccccc 4. dddddd 5. eeeeeee

    quiero ordenarlo de la siguiente manera:

    1. aaaaaaaaaa
    2. bbbbbbbbbbb
    3. cccccccccccccc
    4. dddddd
    5. eeeeeee

    (las letras aaaa, bbbb, etc del ejemplo seria texto) Son unas 750 paginas asi que hacerlo manualmente seria una tarea demorada. Existe algún método para que el UltraEdit lo haga?

    2. Como puedo borrar los números de ese texto ya ordenado?
    es decir que pase de estar asi:

    1. aaaaaaaaaa
    2. bbbbbbbbbbb
    3. cccccccccccccc
    4. dddddd
    5. eeeeeee

    y que me quede asi:

    aaaaaaaaaa
    bbbbbbbbbbb
    cccccccccccccc
    dddddd
    eeeeeee

    Gracias ojala me puedan ayudar

    Responder
    • José Calvo

      Hola Laramjo,
      eso se puede conseguir con expresiones regulares. Para el primer necesitas utilizar los caracteres especiales de salto de línea, que normalemnte son \r\n e incluirlos en la caja de reemplazo.
      Para el segundo deberías buscar algo así: ^[0-9]\. y reemplazarlo por nada.
      Espero que te sirva. Un saludo!

      Responder
  3. Elias González

    Hola. Tengo cero experiencia en expresiones regulares, actualmente estoy emprezando a descubrirlas actualmente y me ha tocado un caso de lo más raro. Tengo una lista de números en dos columnas dentro de un archivo en texto plano y separados por tabulación. La primera columna es la llave, pero la segunda columna contiene valores separados por coma. Lo que quiero hacer es lo siguiente:
    COL A—>COL B
    1—>2,78,4
    2—>9,23,1
    3—>5,8,2

    Lo que quiero hacer es:
    COL A—>COL B
    1—>2
    1—>78
    1—4
    2—>9, etc

    ¿Es posible hacer esto con expresiones regulares? Desde ya te agradezco la ayuda.

    Responder
    • José Calvo

      Hola!
      Perdona por el retraso en responder. Lo que yo haría sería buscar:

      ^(\d+)—>(\d+),(.*?)$

      Y reemplazar por:

      \1—>\3\n\1\2

      Y reemplazarlo tantas veces como números haya en la columna B. Creo que debería funcionar. Saludos!

      Responder
      • Elías Gonzalez

        Gracias! Jejeje. después de mucho tiempo vuelvo a tocar expresiones regulares y vuelvo a caer a tu página. Tengo otra consulta, si no es mucha molestia: Tengo una tabla en texto separado por espacios
        con el siguiente formato:
        ABC-12345 Mon Jan 20/01/2017 17:35:56 Apertura 0 SIS
        ABC-12345 Mon Jan 20/01/2017 17:35:56 Cierre 0 SIS
        0 y SIS son usuario que ejecuta y usuario que autoriza. Estas expresiones se repiten frecuentemente cambiando sólo fecha y hora; sin embargo, hay lineas en las que el formato es:
        Apertura Automática Mon Jan 21/01/2017 07:01:01 SIS
        Señal Reconocida inmediatamente Mon Jan 21/01/2017 07:01:01 SIS

        El ABC-12345 es la llave y las dos últimas filas deberían tener el formato de la primera:
        Cómo inserto el ABC-1245 y reordeno la fecha para que se miren como las primeras expresiones?

        Responder
  4. alejandro B

    buenas noches,
    me pueden ayudar tengo una sola linea de datos de la siguiente forma:

    1234;abcd;0001;2016-09-15;5678;wxyz;0002;2016-09-14;9012;opqr;0003;2016-09-13; ….etc

    quiciera que en la fecha en lugar del “;” dejar un salto de linea
    y que quedara asi:

    1234;abcd;0001;2016-09-15
    5678;wxyz;0002;2016-09-14
    9012;opqr;0003;2016-09-13

    son dos datos, un consecutivo y una fecha
    pero este momento en un infinito reglón
    no se si es posible que cada 4 “;” dejara en salto de linea o filtrar de algún forma “-15;” por ejemplo.
    agradecería su ayuda

    Responder
  5. Victor Adolfo Mosquera Gonzalez

    Hola José

    Mira tengo un texto y necestio dejar solo ciertos renglones de este el resto lo necesito borrar…ejemplo

    primer linea xxx xxxx xxxx xx
    segunda linea xxxx xxxx xxxxx
    cpu yyy yyyy yyyy yyyy yyyyy
    cuarta linea xxx xxx xxx xxxxxx
    cpu yyy yyy yyyy yyyy yyyyy
    sexta linea xxx xxx xxx xxxxx

    Necesito dejar solo las lineas que empiecen por cpu…. como ?

    Responder
  6. Victor Adolfo Mosquera Gonzalez

    Hola José

    Ya logro identificar las lineas que no necesito ([^.CPU(.*)m]$) ->(Se incluye m pues asi termina mi linea) sin embargo solo selecciona el ultimo caracter de dicha linea y al realizar el remplazar pues solo lo hace del ultimo caracter y necesito que elimine todo el texto adicional….

    gracias

    Responder
  7. José Calvo

    Hola Victor!
    He probado la regex que me has enviado y con el ejemplo que dabas no me funcionaba, seleccionaba todos los últimos caracteres.

    Yo lo haría en dos pasos. Primero borrar las líneas que no empiezan por CPU con:
    ^((?!cpu).)+$
    Y después seleccionar el último caracter de la línea:
    ^.*?(.)$

    Espero que te valga. Saludos!

    Responder

Comenta

  • (will not be published)

XHTML: Puedes utilizar estos tags para que tu comentario tenga estilos o hipervínculos: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>