Con Terminal: usando expresións regulares II: substitucións

En min mesmo artigo anterior Comenteille nun nivel básico como funcionan cada un dos caracteres especiais máis usados ​​das expresións regulares. Con estas expresións regulares é posible facer buscas complexas en ficheiros de texto ou na saída doutros comandos. Neste artigo vou explicar como usar o comando sed para atopar e substituír texto dun xeito moito máis poderoso que simplemente cambiar un texto por outro.

Un pouco máis sobre o comando grep

Antes de comezar a falar de sed, gustaríame comentar un pouco máis sobre o comando grep para completar un pouco o explicado no artigo anterior. Todo o que vou dicir será relevante tamén para este. Máis tarde veremos a relación entre isto e as buscas.

Combinando expresións regulares

Moitos dos personaxes especiais dos que falei no artigo anterior pódense combinar, non só con outros personaxes, senón con expresións regulares enteiras. O xeito de facelo é empregar parénteses para formar unha subexpresión. Vexamos un exemplo disto. Comezamos descargando un texto que podemos usar para probar. É unha lista de frases. Para iso imos usar o seguinte comando:

curl http://artigoo.com/lista-de-frases-comparativas-comicas 2>/dev/null | sed -n 's/.*\(.*\.\)<\/p>/\1/gp' > frases

 Isto deixaráche no directorio onde inicia un ficheiro chamado «frases». Podes abrilo para botar unha ollada e botar unhas risas. 🙂

Imos supoñer que queremos atopar as frases que teñan exactamente 6 palabras. A dificultade está en formar unha expresión regular que coincida con cada palabra. Unha palabra é unha secuencia de letras, maiúsculas ou minúsculas, que sería algo así '[a-zA-Z]+', pero tamén tes que especificar que estas letras teñen que estar separadas por outros caracteres que non sexan letras, é dicir, sería algo así '[a-zA-Z]+[^a-zA-Z]+'. Lembremos: o "^" como primeiro carácter entre parénteses indica que queremos coincidir con caracteres que non están nos rangos e o "+" indica 1 ou máis caracteres.

Xa temos unha expresión regular que pode coincidir cunha palabra. Para emparellalo con 6, haberá que repetilo 6 veces. Para iso empregamos as teclas, pero non serve de nada poñelas '[a-zA-Z]+[^a-zA-Z]+{6}', porque o 6 repetiría a última parte da expresión regular e o que queremos é repetilo todo, entón o que tes que poñer é isto: '([a-zA-Z]+[^a-zA-Z]+){6}'. Coas parénteses formamos unha subexpresión e coas chaves repetímola 6 veces. Agora só precisa engadir un "^" diante e un "$" na parte traseira para que coincida con toda a liña. O comando é o seguinte:

grep -E '^([a-zA-Z]+[^a-zA-Z]+){6}$' frases

E o resultado é o que queriamos:

É máis cantado que o Macarena. Estás máis acabado que Luis Aguilé. Tes menos cultura que unha pedra. Sabes máis idiomas que Cañita Brava. Ten máis engurras que Tutan Khamón. Vostede sabe menos que Rambo sobre o coidado dos nenos.

Teña en conta que poñemos o parámetro -E porque queremos usar expresións regulares estendidas para que o "+" funcione. Se usásemos os básicos, teriamos que escapar entre parénteses e chaves.

Referencias posteriores ou referencias posteriores

Se tes un corrector ortográfico instalado, probablemente teñas unha lista de palabras en /usr/share/dict/words. Se non, pode instalalo en arch con:

sudo pacman -S words

Ou en debian con:

sudo aptitude install dictionaries-common

Se queres, podes botar unha ollada ao ficheiro para ver que palabras ten. En realidade é unha ligazón ao ficheiro de palabras do idioma no que está a túa distribución. Pode ter varios ficheiros de palabras instalados ao mesmo tempo.

Imos usar ese ficheiro. Resulta que temos moita curiosidade por coñecer todos os palindromos de sete letras que hai. Para os que non o saiban: Un palíndromo é unha palabra capicúa, é dicir, pódese ler de esquerda a dereita e de dereita a esquerda. Tentemos o seguinte comando:

grep '^\(.\)\(.\)\(.\).\3\2\1$' /usr/share/dict/words

Parece un pouco raro, non? Se o probamos, o resultado dependerá do idioma da súa distribución e das palabras da súa lista, pero no meu caso, coa lingua española, o resultado é este:

anilina anilina rolando

Vexamos como funciona esta expresión regular.

Ademais do "^" e o "$", que xa sabemos para que serve, o primeiro que vemos á esquerda son tres grupos de puntos entre parénteses. Non se deixe confundir polas barras diante de cada paréntese. Son para escapar das parénteses porque estamos a usar expresións regulares básicas, pero non teñen outro significado. O importante é que esteamos a pedir tres caracteres cos puntos, pero cada un deles está entre parénteses. Isto é para gardar os caracteres que coincidan con eses puntos para que poidan ser referenciados de novo a partir da expresión regular. Este é outro uso de parénteses que será útil máis tarde para facer substitucións.

Aquí é onde veñen os tres números de abaixo coa barra dianteira. Neste caso, a barra é importante. Isto indica que o número de abaixo é unha referencia atrás e refírese a un dos parénteses anteriores. Por exemplo: \ 1 refírese ao primeiro paréntese, \ 2 ao segundo, etc.

Noutras palabras, coa expresión regular que puxemos, o que buscamos son todas as palabras que empecen por catro letras e despois teñen unha letra igual á terceira, outra igual á segunda e outra igual á primeira. O resultado son os palíndromos de sete letras que figuran na lista de palabras. Tal e como queriamos.

Se usásemos expresións regulares estendidas, non teriamos que escapar das parénteses, pero coas expresións regulares estendidas as referencias de fondo non funcionan en todos os programas porque non están estandarizadas. Non obstante, con grep funcionan, polo que pode ser outro xeito de facer o mesmo. Podes probalo se queres.

Expresións de substitución: o comando sed

Ademais de buscar, un dos mellores usos das expresións regulares é substituír textos complexos. Para facelo, un xeito de facelo é co comando sed. O poder do comando sed vai moito máis alá de substituír o texto, pero aquí vou empregalo para iso. A sintaxe que vou usar con este comando é a seguinte:

sed [-r] 's/REGEX/REPL/g' FICHERO

Ou tamén:

COMANDO | sed [-r] 's/REGEX/REPL/g'

Onde REGEX será a expresión regular de busca e REPL a substitución. Ten en conta que este comando non substitúe nada no ficheiro que indicamos, pero o que fai é amosarnos o resultado da substitución no terminal, polo que non te asustes cos comandos que vou poñer a continuación. Ningún deles vai modificar ningún ficheiro do seu sistema.

Comecemos cun exemplo sinxelo. Todos temos varios ficheiros de configuración no directorio / etc que normalmente teñen comentarios que comezan por "#". Supoñamos que queremos ver un destes ficheiros sen os comentarios. Por exemplo, vou facelo co fstab. Podes probar co que queiras.

sed 's/#.*//g' /etc/fstab

Non vou poñer aquí o resultado do comando porque depende do que teñas no teu fstab, pero se comparas a saída do comando co contido do ficheiro verás que todos os comentarios desapareceron.

Neste comando a expresión de busca é «#.*", Isto é un" # "seguido de calquera número de caracteres, é dicir, os comentarios. E a expresión de substitución, se observas as dúas barras seguidas, verás que non hai ningunha, polo que o que fai é substituír os comentarios por nada, é dicir, borralos. Máis sinxelo imposible.

Agora imos facer o contrario. Supoñamos que o que queremos é comentar todas as liñas do ficheiro. Intentemos así:

sed 's/^/# /g' /etc/fstab

Verás que, na saída do comando, todas as liñas comezan cunha marca hash e un espazo en branco. O que fixemos é substituír o comezo da liña por «# «. Este tamén é un exemplo bastante sinxelo onde o texto a substituír sempre é o mesmo, pero agora imos complicalo un pouco máis.

A graza das substitucións é que na expresión de substitución podes usar referencias posteriores como as que che dixen antes. Volvamos ao arquivo de frases que descargamos ao comezo do artigo. Imos poñer entre parénteses todas as maiúsculas que hai, pero farémolo cun comando:

sed 's/\([A-Z]\)/(\1)/g' frases

Aquí temos unha referencia atrás na expresión de substitución que se refire aos parénteses da expresión de busca. Os parénteses da expresión de substitución son parénteses normais. Na expresión de substitución non teñen un significado especial, póñense tal cal. O resultado é que todas as maiúsculas son substituídas por esa mesma letra, sexa cal for, con parénteses ao redor.

Hai outro carácter que tamén se pode usar na expresión de substitución, é "&" e substitúese por todo o texto coincidente coa expresión de busca. Un exemplo disto podería ser poñer todas as frases do ficheiro entre comiñas. Isto pódese conseguir con este comando:

sed 's/.*/"&"/g' frases

O funcionamento deste comando é moi similar ao anterior, só que agora o que substituímos é toda a liña coa mesma liña con comiñas ao seu redor. Dado que estamos a usar "&", non precisamos poñer parénteses.

Algúns comandos útiles con expresións regulares

Aquí tes algúns comandos que me parecen útiles ou curiosos e que utilizan expresións regulares. Con estes comandos a utilidade das expresións regulares é moito mellor que cos exemplos que che puxen ata agora, pero pareceume importante explicar algo sobre como funcionan as expresións regulares para entendelas.

  • Mostrar seccións dunha páxina de manual:

man bash | grep '^[A-Z][A-Z ]*$'

Por suposto, podes cambiar o comando bash ao que queiras. E despois desde o home, podes ir directamente á sección que che interesa usando, por suposto, unha expresión regular. Preme «/» para comezar a buscar e escribir «^ALIASES$»Para ir á sección ALIASES, por exemplo. Creo que este é o primeiro uso que comecei a facer das expresións regulares hai uns anos. Pasar por algunhas páxinas do manual é case imposible sen un truco coma este.

  • Mostrar os nomes de todos os usuarios da máquina, incluídos os especiais:

sed 's/\([^:]*\).*/\1/' /etc/passwd

  • Mostrar nomes de usuario, pero só aqueles con shell:

grep -vE '(/false|/nologin)$' /etc/passwd | sed 's/\([^:]*\).*/\1/g'

Realmente pódese facer cunha única expresión regular, pero o xeito de facelo vai máis alá do que che dixen nestes artigos, polo que o fixen combinando dous comandos.

  • Insira unha coma antes dos últimos tres díxitos de todos os números do ficheiro de números:

sed 's/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g' numbers

Só funciona con números de ata 6 díxitos, pero pódese chamar máis dunha vez para colocar separadores nos outros grupos de tres díxitos.

  •  Extrae todos os enderezos de correo electrónico dun ficheiro:

grep -E '\<[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}\>' FICHERO

  • Separe o día, o mes e o ano de todas as datas que aparecen nun ficheiro:

sed -r 's/([0-9]{2})[/-]([0-9]{2})[/-]([0-9]{4})/Día: \1, Mes: \2, Año: \3/g' FICHERO

  • Descubra a nosa IP local:

/sbin/ifconfig | grep 'inet .*broadcast' | sed -r 's/[^0-9]*(([0-9]+\.){3}[0-9]+).*/\1/g'

Isto tamén se pode facer cun comando sed único, pero é mellor que o separe nun grep e un sed por simplicidade.

Algúns enderezos útiles

Aquí tes algúns enderezos que poden ser útiles relacionados coas expresións regulares:

  • Biblioteca de expresións regulares: Esta é unha biblioteca de expresións regulares onde podes buscar expresións regulares relacionadas co tema que che interesa. Para buscar enderezos web, identificación ou calquera outra cousa.
  • RegExr: Un comprobador de expresións regulares en liña. Permite introducir un texto e aplicarlle unha expresión regular, xa sexa buscar ou substituír. Ofrece información sobre a expresión regular e tes algunhas opcións para cambiar o seu comportamento.
  • Probador de expresións regulares: É un complemento para Firefox que permite comprobar expresións regulares dende o navegador.

Conclusión

De momento iso é todo. As expresións regulares son complexas pero útiles. Leva tempo aprendelos, pero se es coma min, xogar con eles parecerá divertido e, pouco a pouco, irás dominándoos. É todo un mundo. Habería moito que dicir aínda, sobre os cuantificadores preguiceiros, a regla ao estilo PERL, a multilínea, etc. E entón cada programa ten as súas características e as súas variantes, polo que o mellor consello que lle podo dar é mirar sempre a documentación do programa que está a usar cada vez que ten que escribir unha expresión regular nun novo programa.

Ei! ... OLA! … ESPERTA! ... QUE FACEDES TODOS DURMIDO? 🙂

Fuentes

Tirei de aquí algunhas das ideas e exemplos para as expresións regulares neste artigo:


O contido do artigo adhírese aos nosos principios de ética editorial. Para informar dun erro faga clic en aquí.

15 comentarios, deixa os teus

Deixa o teu comentario

Enderezo de correo electrónico non será publicado.

*

*

  1. Responsable dos datos: Miguel Ángel Gatón
  2. Finalidade dos datos: controlar SPAM, xestión de comentarios.
  3. Lexitimación: o seu consentimento
  4. Comunicación dos datos: os datos non serán comunicados a terceiros salvo obrigación legal.
  5. Almacenamento de datos: base de datos aloxada por Occentus Networks (UE)
  6. Dereitos: en calquera momento pode limitar, recuperar e eliminar a súa información.

  1.   elav dixo

    Maxistralmente !!!

    1.    hexborg dixo

      Non é tan malo, pero moitas grazas. Espero que á xente lle guste. 🙂

      1.    oscar dixo

        Gústame ha!

        1.    hexborg dixo

          Entón debín facer algo ben. LOL !! 🙂

          Moitas grazas polo teu comentario.

          1.    Blaire pascal dixo

            Carallo siga escribindo home, siga así.

          2.    hexborg dixo

            @Blaire Pascal: comentarios como o teu o animan. 🙂 Moitas grazas !!

      2.    Citux dixo

        A min tamén me gustou ... grazas 🙂

        1.    hexborg dixo

          Grazas polo comentario. Espero escribir algúns máis. 🙂

  2.   mariano dixo

    As túas publicacións son fantásticas, aprendes moito, máis ben, aprendes a realizar tarefas dun xeito elegante e eficiente.

    ¿Pensaches en recompilar todas as túas publicacións de scripts de shell? Ordenado nun pdf sería un gran manual.

    Ánimo e moitas grazas!

    1.    hexborg dixo

      Moitas grazas!! Non é unha mala idea. Polo momento só hai dous, pero pensareino máis adiante. 🙂

  3.   Kiyov dixo

    moi bo artigo, 5+.

    1.    hexborg dixo

      Grazas. Alégrome de que che guste. 🙂

  4.   Sebastian dixo

    Excelente! Necesito cambiar a seguinte expresión e non sei como facelo:
    192.168.0.138/Server por 192.168.0.111/data
    O problema reside no símbolo "/".
    Estou a usar o comando:
    atopar. -name "* .txt" -exec sed -i 's / TEXT1 / TEXT2 / g' {} \;
    Que se usa para realizar este tipo de tarefas remisivamente, pero non podo ...
    Alguén sabe como debería facelo?
    Abrazo!
    Seba

    1.    hexborg dixo

      O que tes que facer é escapar do personaxe así:

      atopar. -name "* .txt" -exec sed -i 's / \ / Server / \ / data / g' {} \;

      Tamén pode usar outro separador en sed. Non ten por que ser un bar. Sed permite usar calquera personaxe. Por exemplo, isto sería máis claro:

      atopar. -name "* .txt" -exec sed -i | | Servidor | / data | g '{} \;

      E se vai copiar e pegar os comandos deste comentario, teña coidado coas comiñas, que wordpress as cambia polas tipográficas. 🙂

      Saúdos.

  5.   Sebastian dixo

    Excelente !!!!
    Busco esta solución dende hai moito tempo.
    Aquí deixo o comando completo que usei

    atopar. -name "* .txt" -exec sed -i 's | 192 \ .168 \ .0 \ .238 \ / Server | 192 \ .168 \ .0 \ .111 \ / data | g' {} \;

    A vantaxe deste comando é que cambia todos os ficheiros .txt (ou a extensión que desexa) recursivamente ... Hai que ter moito coidado.
    Pero é moi útil !!!

    Ben, grazas por todo e mil parabéns a todo o grupo.
    Sempre os lin dende o correo!
    Apertas
    Seba

bool (verdadeiro)