Con Terminal: usando expresións regulares

Unha das cousas que sempre me encantou do terminal Linux é o que podes conseguir usando expresións regulares. Se precisamos atopar texto complicado ou substituílo por outra cousa, o uso de expresións regulares pode simplificar moito o traballo. Comecemos polo comezo:

AVISO: Esta publicación é unha dor de cu. Ler este post todo o tempo pode provocar a perda de coñecemento. Fai pausas intermedias ou pregunta ao teu médico ou farmacéutico antes de ler a publicación completa.

Que é unha expresión regular?

Unha expresión regular é unha serie de caracteres especiais que nos permiten describir un texto que queremos atopar. Por exemplo, se quixésemos buscar a palabra "linux" sería suficiente con meter esa palabra no programa que estamos a usar. A palabra en si é unha expresión regular. Ata agora parece moi sinxelo, pero e se queremos atopar todos os números nun ficheiro determinado? Ou todas as liñas que comezan con maiúscula? Neses casos xa non podes poñer unha palabra sinxela. A solución é empregar unha expresión regular.

Expresións regulares vs. patróns de ficheiro.

Antes de entrar no tema das expresións regulares, quero aclarar un malentendido común sobre as expresións regulares. Unha expresión regular non é o que poñemos como parámetro en comandos como rm, cp, etc. para referirse a varios ficheiros do disco duro. Ese sería un patrón de ficheiro. As expresións regulares, aínda que son similares porque usan algúns caracteres comúns, son diferentes. Un patrón de ficheiro dispárase contra os ficheiros do disco duro e devolve os que coinciden completamente co patrón, mentres que unha expresión regular dispárase contra un texto e devolve as liñas que conteñen o texto buscado. Por exemplo, a expresión regular correspondente ao patrón *.* sería algo así ^.*\..*$

Tipos de expresións regulares.

Non todos os programas usan as mesmas expresións regulares. Nin moito menos. Existen varios tipos de expresións regulares máis ou menos estándar, pero hai programas que cambian lixeiramente a sintaxe, inclúen as súas propias extensións ou incluso usan caracteres completamente diferentes. Polo tanto, cando quere usar expresións regulares cun programa que non coñece ben, o primeiro que hai que facer é mirar o manual ou a documentación do programa para ver como son as expresións regulares que recoñece.

En primeiro lugar, hai dous tipos principais de expresións regulares contidas no estándar POSIX, que é o que utilizan as ferramentas Linux. Son as expresións regulares básicas e estendidas. Moitos dos comandos que funcionan con expresións regulares, como grep ou sed, permítenlle usar estes dous tipos. Falarei deles a continuación. Tamén hai as expresións regulares ao estilo PERL e logo hai programas como vim ou emacs que usan variantes destas. Dependendo do que queiramos facer, pode ser máis axeitado usar un ou outro.

Proba de expresións regulares.

A sintaxe das expresións regulares non é nada trivial. Cando teñamos que escribir unha expresión regular complicada estaremos diante dunha cadea de caracteres especiais imposibles de entender a primeira vista, polo que para aprender a usalos é fundamental ter un xeito de facer todas as probas que queremos e ver os resultados facilmente. É por iso que agora vou poñer varios comandos cos que podemos facer as probas e experimentar todo o que necesitamos ata que dominemos as expresións regulares.

O primeiro é o comando grep. Este é o comando que usaremos con máis frecuencia para facer buscas. A sintaxe é a seguinte:

grep [-E] 'REGEX' FICHERO
COMANDO | grep [-E] 'REGEX'

Recomendo poñer expresións regulares entre comiñas simples para que o shell non se adapte. O primeiro xeito é atopar unha expresión regular nun ficheiro. O segundo permite filtrar a saída dun comando a través dunha expresión regular. Por defecto, grep usa expresións regulares básicas. A opción -E é para usar expresións regulares estendidas.

Un truco que pode axudarnos a ver como funcionan as expresións regulares para habilitar o uso da cor no comando grep. Deste xeito, resaltarase a parte do texto que coincida coa expresión regular que estamos a usar. Para activar a cor no comando grep, asegúrese de que a variable de entorno GREP_OPTIONS conter en valor --color, que se pode facer con este comando:

GREP_OPTIONS=--color

Podemos poñelo no .bashrc para telo sempre activado.

Outra forma de usar expresións regulares é empregando o comando sed. Isto é máis axeitado para substituír texto, pero tamén se pode usar para buscar. A sintaxe sería así:

sed -n[r] '/REGEX/p' FICHERO
COMANDO | sed -n[r] '/REGEX/p'

O comando sed tamén usa expresións regulares básicas por defecto, pode usar expresións regulares estendidas coa opción -r.

Outro comando ao que tamén quero nomear é awk. Este comando pode usarse para moitas cousas, xa que permite escribir guións na súa propia linguaxe de programación. Se o que queremos é buscar unha expresión regular nun ficheiro ou na saída dun comando, o xeito de usalo sería o seguinte:

awk '/REGEX/' FICHERO
COMANDO | awk '/REGEX/'

Este comando sempre usa expresións regulares estendidas.

Para facer as nosas probas tamén necesitaremos un texto que sirva de exemplo para buscalo. Podemos usar o seguinte texto:

- Lista de páginas wiki:

ArchLinux: https://wiki.archlinux.org/
Gentoo: https://wiki.gentoo.org/wiki/Main_Page
CentOS: http://wiki.centos.org/
Debian: https://wiki.debian.org/
Ubuntu: https://wiki.ubuntu.com/

- Fechas de lanzamiento:

Arch Linux: 11-03-2002
Gentoo: 31/03/2002
CentOs: 14-05-2004 03:32:38
Debian: 16/08/1993
Ubuntu: 20/10/2004

Desde Linux Rulez.

Este é o texto que vou empregar para os exemplos do resto da publicación, polo que recomendo que o copie nun ficheiro para que o teña a man desde o terminal. Podes poñer o nome que queiras. Chameino rexex.

Lección inicial.

Agora temos todo o necesario para comezar a probar expresións regulares. Imos aos poucos. Vou poñer varios exemplos de buscas con expresións regulares nas que explicarei para que serve cada personaxe. Non son moi bos exemplos, pero dado que vou ter un post moi longo, non quero complicalo máis. E só vou rascar a superficie do que se pode facer con expresións regulares.

O máis sinxelo de todos é buscar unha palabra específica, por exemplo, supoñamos que queremos buscar todas as liñas que conteñan a palabra "Linux". Isto é o máis sinxelo, xa que só temos que escribir:

grep 'Linux' regex

E podemos ver o resultado:

ArcoLinux: https://wiki.archlinux.org/ Arch Linux: 11-03-2002 De Linux Rulez.

Estas son as tres liñas que conteñen a palabra "Linux" que, se empregamos o truco de cores, aparecerán resaltadas. Teña en conta que recoñece a palabra que estamos a buscar aínda que forme parte dunha palabra máis longa como en "ArchLinux". Non obstante, non destaca a palabra "linux" que aparece na URL "https://wiki.archlinux.org/". Isto é porque aparece alí con minúscula "l" e buscámolo en maiúscula. O comando grep ten opcións para iso, pero non vou falar delas nun artigo sobre expresións regulares.

Con esta sinxela proba podemos sacar a primeira conclusión:

  • Un personaxe normal posto nunha expresión regular coincide con si mesmo.

O que quere dicir que se pon a letra "a" buscará a letra "a". Parece lóxico, non? 🙂

Agora supoña que queremos buscar a palabra "CentO" seguida de calquera carácter, pero só un carácter. Para iso podemos usar o carácter ".", Que é un comodín que coincide con calquera carácter, pero só un:

grep 'CentO.' regex

E o resultado é:

CentOS: http://wiki.centos.org/
CentOs: 14-05-2004 03:32:38

O que significa que inclúe o "S" en "CentOS" aínda que nun caso é maiúscula e noutro en minúscula. Se algún outro personaxe aparecese nese lugar, tamén o incluiría. Xa temos a segunda regra:

  • O personaxe "." coincide con calquera personaxe.

Xa non é tan trivial como parecía, pero con isto non podemos facer moito. Imos un pouco máis alá. Supoñamos que queremos atopar as liñas nas que aparecen o ano 2002 e 2004. Parecen dúas buscas, pero pódense facer á vez así:

grep '200[24]' regex

O que significa que queremos atopar o número 200 seguido de 2 ou 4. E o resultado é este:

ArchLinux: 11-03-2002
Gentoo: 31/03 /2002
CentOS: 14-05-2004 03:32:38
Ubuntu: 20/10/2004

O que nos leva á terceira regra:

  • Varios caracteres entre corchetes coinciden con calquera dos caracteres entre corchetes.

Os corchetes dan máis xogo. tamén se poden usar para excluír caracteres. Por exemplo, supoñamos que queremos atopar sitios onde apareza o carácter ":", pero non vai seguido de "/". O comando sería así:

grep ':[^/]' regex

Simplemente trátase de poñer un "^" como primeiro personaxe dentro do soporte. Podes poñer todos os personaxes que queiras a continuación. O resultado deste último comando é o seguinte:

ArchLinux: https://wiki.archlinux.org/
Gentoo: https://wiki.gentoo.org/wiki/Main_Page
CentOS: http://wiki.centos.org/
Debian: https://wiki.debian.org/
Ubuntu: https://wiki.ubuntu.com/
Arch Linux: 11-03-2002 Gentoo: 31/03/2002 CentOs: 14-05-2004 03:32:38 Debian: 16/08/1993 Ubuntu: 20 / 10 / 2004

Agora están resaltados os ":" detrás dos nomes de distribución, pero non os dos URL porque os URL teñen "/" despois deles.

  • Poñer o carácter "^" ao comezo dun paréntese coincide con calquera carácter agás os demais caracteres do paréntesis.

Outra cousa que podemos facer é especificar un rango de caracteres. Por exemplo, para buscar calquera número seguido dun "-" sería así:

grep '[0-9]-' regex

Con isto estamos a especificar un carácter entre 0 e 9 e despois un signo menos. Vexamos o resultado:

ArchLinux: 11-03-CentOs do 2002: 14-05-2004: 03: 32: 38

Pódense especificar varios rangos entre parénteses para mesturar incluso rangos con caracteres individuais.

  • Situar dous caracteres separados por "-" dentro dos corchetes coincide con calquera carácter dentro do intervalo.

A ver agora se podemos seleccionar a primeira parte das URL. A que di "http" ou "https". Só se diferencian nos "s" finais, polo que imos facelo do seguinte xeito:

grep -E 'https?' regex

O signo de interrogación úsase para facer opcional o carácter á súa esquerda. Pero agora engadimos a opción -E ao comando. Isto débese a que o interrogatorio é unha característica das expresións regulares estendidas. Ata agora empregabamos expresións regulares básicas, polo que non había necesidade de poñer nada. Vexamos o resultado:

ArchLinux: https: //wiki.archlinux.org/ Gentoo: https: //wiki.gentoo.org/wiki/Main_Page CentOS: http: //wiki.centos.org/ Debian: https: //wiki.debian.org/ Ubuntu: https: //wiki.ubuntu.com/

Así que xa temos unha nova regra:

  • Un personaxe seguido de "?" coincide con ese carácter ou ningún. Isto só é válido para expresións regulares estendidas.

Agora imos atopar dúas palabras completamente diferentes. Vexamos como atopar as liñas que conteñen tanto a palabra "Debian" como "Ubuntu".

grep -E 'Debian|Ubuntu' regex

Coa barra vertical podemos separar dúas ou máis expresións regulares diferentes e atopar as liñas que coincidan con algunha delas:

Debian: https://wiki.debian.org/
Ubuntu: https://wiki.ubuntu.com/
Debian: 16 / 08 / 1993
Ubuntu: 20 / 10 / 2004
  • O personaxe «|» serve para separar varias expresións regulares e coincidir con algunha delas. Tamén é específico de expresións regulares ampliadas.

Continuemos. Agora imos buscar a palabra "Linux", pero só onde non está pegada a outra palabra á esquerda. Podemos facelo así:

grep '\

Aquí o carácter importante é "<", pero hai que escapar poñendo "\" diante para que grep o interprete como un carácter especial. O resultado é o seguinte:

Arco Linux: 11-03-2002 De Linux Rulez.

Tamén pode usar "\>" para buscar palabras que non están xuntas. Imos cun exemplo. Tentemos este comando:

grep 'http\>' regex

O resultado que produce é este:

CentOS: http: //wiki.centos.org/

Saíu "Http", pero non "https", porque en "https" aínda hai un carácter á dereita do "p" que pode formar parte dunha palabra.

  • Os caracteres "<" e ">" coinciden respectivamente co comezo e o final dunha palabra. Estes caracteres deben escapar para que non se interpreten como caracteres literais.

Imos coas cousas un pouco máis complicadas. O carácter "+" coincide co carácter á esquerda, repetido polo menos unha vez. Este carácter só está dispoñible con expresións regulares ampliadas. Con el podemos buscar, por exemplo, secuencias de varios números seguidos que comecen por ":".

grep -E ':[0-9]+' regex

Resultado:

CentOs: 14/05/2004 03: 32: 38

Tamén se destaca o número 38 porque tamén comeza por ":".

  • O carácter "+" coincide co carácter á esquerda, repetido polo menos unha vez.

Tamén pode controlar o número de repeticións usando "{" e "}". A idea é poñer entre chaves un número que indique o número exacto de repeticións que queremos. Tamén podes poñer un rango. Vexamos exemplos dos dous casos.

Primeiro imos atopar todas as secuencias de catro díxitos que hai:

grep '[0-9]\{4\}' regex

Teña en conta que ten que escapar das chaves se se utilizan expresións regulares básicas, pero non se se usan expresións estendidas. Con estendido sería así:

grep -E '[0-9]{4}' regex

E o resultado en ambos casos sería este:

ArchLinux: 11-03-2002
Gentoo: 31/03 /2002
CentOS: 14-05-2004 03:32:38
Debian: 16/08/1993
Ubuntu: 20/10 /2004
  • Os caracteres "{" e "}" cun número entre eles coinciden co carácter anterior repetido o número de veces especificado.

Agora o outro exemplo coas chaves. Supoñamos que queremos atopar palabras que teñan entre 3 e 6 letras minúsculas. Poderiamos facer o seguinte:

grep '[a-z]\{3,6\}' regex

E o resultado sería este:

- List de páxinas wiki: ArchLinux: https: //wiki.Archlinux.org/ Gtamén: https: //wiki.xentoo.org/wiki/MAin_Pidade
CentOS: http: //wiki.centos.org/ Debian: https: //wiki.debian.org/ OUsen saída: https: //wiki.ubuntu.con/ - Fbotas de menos de Lanzamento: Arch Linux: 11-03-2002 Gtamén: 31/03/2002 CentOs: 14-05-2004 03:32:38
Debian: 16/08/1993 Usen saída: 20/10/2004 DÉ Linux Rulez.

O que, como podes ver, non se parece moito ao que queriamos. Isto é porque a expresión regular atopa as letras dentro doutras palabras que son máis longas. Imos probar esta outra versión:

grep '\<[a-z]\{3,6\}\>' regex

Resultado:

- Lista de páxinas wiki: ArchLinux: https: //wiki.archlinux.org/ Gentoo: https: //wiki.xentoo.org/wiki/ Main_Page CentOS: http: //wiki.centos.org/ Debian: https: //wiki.debian.org/ Ubuntu: https: //wiki.ubuntu.con/

Isto xa se parece máis ao que queriamos. O que fixemos é esixir que a palabra comece xusto antes da primeira letra e remate xusto despois da última.

  • Os caracteres "{" e "}" con dous números entre eles separados por unha coma coinciden co carácter anterior repetido o número de veces indicado polos dous números.

Vexamos agora un personaxe que é un punto "+". É "*" e o seu funcionamento é moi similar, só que coincide con calquera número de caracteres incluído cero. É dicir, fai o mesmo que o "+" pero non require que o personaxe á súa esquerda apareza no texto. Por exemplo, probemos a buscar os enderezos que comezan en wiki e rematan en org:

grep 'wiki.*org' regex

Vexamos o resultado:

ArchLinux: https: //wiki.archlinux.org/ Gentoo: https: //wiki.gentoo.org/ wiki / Main_Page CentOS: http: //wiki.centos.org/ Debian: https: //wiki.debian.org/

Perfecto.

Agora o último personaxe que imos ver. O carácter "\" úsase para escapar do personaxe á súa dereita de xeito que perde o seu significado especial. Por exemplo: Supoñamos que queremos localizar as liñas que rematan nun punto. O primeiro que se nos ocorrería podería ser isto:

grep '.$' regex

O resultado non é o que buscamos:

- Lista de páxinas wiki:
ArchLinux: https://wiki.archlinux.org/
Gentoo: https://wiki.gentoo.org/wiki/Main_Page
CentOS: http://wiki.centos.org/
Debian: https://wiki.debian.org/
Ubuntu: https://wiki.ubuntu.com/
- Fechas de lanzamento: Arch Linux: 11-03-2002
Gentoo: 31/03/2002
CentOs: 14-05-2004 03:32:38
Debian: 16/08/1993
Ubuntu: 20/10/2004
Desde Linux Rulez.

Isto débese a que o "." coincide con calquera cousa, de xeito que a expresión regular coincida co último carácter de cada liña sexa cal sexa. A solución é esta:

grep '\.$' regex

Agora o resultado é o que queremos:

Desde Linux Rulez.

Xogo rematado

Aínda que o tema das expresións regulares é tan complexo que daría por unha serie de artigos, creo que xa che dei bastante dor. Se conseguiches chegar, parabéns. E se leu todo isto dunha soa vez, tome unha aspirina ou algo así, porque non pode ser bo.

De momento iso é todo. Se che gusta este artigo, quizais poida escribir outro. Mentres tanto, recoméndoche que probes todas as expresións regulares do terminal para ver con claridade como funcionan. E lembre: só Chuck Norris pode analizar HTML usando expresións regulares.

 


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

28 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.   Ezequiel dixo

    Que sería da nosa vida sen a rexex?
    O artigo é moi útil, pero ireino lendo pouco a pouco. Moitas grazas.

    1.    hexborg dixo

      Grazas polo comentario. Aínda non creo que saíra o meu artigo. 🙂 Saíu con algún erro, pero espero que sexa útil. 🙂

  2.   Scalibur dixo

    Grazasssssssss! ..

    Hai un tempo tiven que estudar un pouco sobre as expresións regulares .. .. Grazas por ensinar .. e a guía paso a paso para aprender cada unha delas ..

    Moi ben! .. .. Vou coller esa aspirina .. ee

    1.    hexborg dixo

      Es Benvido. Ánimo e que as expresións regulares non poden contigo. 🙂

  3.   tanrax dixo

    Fantástico post! Gran traballo. Pregúntome cantas horas tardaches 😀

    1.    hexborg dixo

      LOL !! A pregunta é: cantas horas me levaría se dixera todo o que pretendía dicir? Infinito !! 🙂

  4.   tammuz dixo

    unha cousa que non sabía, bo artigo!

    1.    hexborg dixo

      Grazas. É un pracer compartilo contigo.

  5.   helena_ryuu dixo

    gran explicación. parabéns! realmente útil!

    1.    hexborg dixo

      Alégrome de que che resultase útil. Por iso é un pracer escribir.

  6.   anti dixo

    Isto debería ir a algún lugar especial. Como o Destacado pero que teñen unha utilidade moi específica. Moi útil, aínda que me gustaría que se aplicase a Vim.

    1.    hexborg dixo

      Esa é unha cuestión de preguntarme. Teño algúns artigos máis sobre expresións regulares en mente. E podería falar de vim neles. Ten algunhas diferenzas do que expliquei neste artigo. É cuestión de seguir adiante. 🙂

  7.   Fernando dixo

    Bo!

    O teu artigo é moi bo, é curioso, recentemente (agora mesmo) publiquei na miña páxina web unha entrada que levo preparando uns días onde recollín unha lista de metacaracteres para expresións regulares e algúns exemplos. E era xusto entrar desde DesdeLinux e ver unha entrada sobre o mesmo tema.

    Se é algún consolo, o meu é MOITO MÁIS COUSA 😀

    Certamente a expresión regular é unha das cousas máis útiles, normalmente úsoas para recortar a saída dos comandos e gardar a parte que me interesa e despois interactuar con ela nun script bash, por exemplo. Tamén os usei moito na universidade e son de vital importancia na construción de compiladores (na definición de lexicográficos e de analizadores). En definitiva, todo un mundo.

    Un saúdo e moi moi bo traballo.

    1.    hexborg dixo

      Moitas grazas.

      Tamén me gustou o teu artigo. É máis conciso que o meu. Pode servir como referencia rápida. É unha casualidade que as escribamos ao mesmo tempo. Podes ver que a xente está interesada no tema. 🙂

  8.   Elery dixo

    Expresións regulares para maniquíes =), agora estou máis claro para min, por certo, un xeito de ter a saída con cor para grep é crear un alias en .bashrc alias grep = 'grep –color = sempre', no caso de que funciona para alguén.

    lembranzas

    1.    hexborg dixo

      Certo. Esa é outra forma de facelo. Grazas pola entrada. 🙂

  9.   KZKG ^ Gaara dixo

    O_O ... anaco de contribución !!! O_O ...
    Moitas grazas pola publicación, estiven agardando algo así por un tempo jejeje, déixoo aberto para lelo con calma na casa sen cero problema para concentrarme jejejeje.

    Grazas polo artigo, de verdade 😀

    1.    hexborg dixo

      Sabía que che gustaría. LOL !! A verdade é que faltan moitas cousas, pero xa teño presente unha segunda parte. 🙂

  10.   Eliecer Tates dixo

    Estupendo artigo, se o lera onte, a clase que impartín hoxe sería aínda máis sinxela para os meus alumnos.

    1.    hexborg dixo

      LOL !! Mágoa que cheguei tarde, pero contento de que sexa útil. 🙂

  11.   LeoToro dixo

    Por fin !!!, a publicación é moi boa ... Por fin atopei algo que explica claramente as expresións regulares ... ..

    1.    hexborg dixo

      Hai moita información por aí, pero é máis difícil atopar algo que sexa fácil de entender. Estou contento de encher ese oco. 🙂

      Saúdos.

  12.   Shakespeare Rodas dixo

    Ola, necesito axuda, teño que facer unha busca en / var / logs co formato: yymmdd e os rexistros veñen como 130901.log -130901.log, teño que buscar todos os que están entre o 1 de setembro e o 11 de outubro, O único que conseguín foi eliminar todo setembro pero non sei como facer a cadea completa:

    ex: 1309 [0-3] devólveme os rexistros entre o 1 de setembro e o 30 de setembro, pero non sei como entrar tamén na mesma cadea do 1 ao 11 de outubro.

    1.    hexborg dixo

      Facelo usando expresións regulares é un pouco complicado. Ocórreme que algo así pode funcionar:

      13(09[0-3]|10(0|1[01]))

      É unha expresión regular estendida. Non di que ferramenta está a empregar, polo que non podo darlle máis detalles.

      De todos os xeitos creo que este é o caso en lugar de usar expresións regulares é mellor facelo con find. Podes probar algo así:

      atopar. -newermt '01 sep '-a! -newermt '11 oct '-print

      Sorte. Espero que isto poida axudarche.

  13.   chipo dixo

    Ola! Primeiro de todo, quería agradecerche o teu traballo xa que esta páxina está dentro dos meus "3 mellores" dos mellores sitios de Linux.
    Estaba practicando e non sabía por que un RegExp nun número de teléfono non funcionaba para min e era que me faltaba o "-E" (do que me dei conta grazas a esta publicación).
    Quería preguntarche se non coñeces un bo pdf ou sitio onde hai exercicios en RegExp, aínda que cun pouco de imaxinación podes practicar inventándoos ti mesmo.

    Un saúdo, Pablo.

  14.   Caly dixo

    Moi ben, acabo de lelo todo, e si agora necesito unha aspirina 🙂

  15.   Oscar dixo

    A mellor explicación que vin das expresións regulares. O meu agradecemento ao autor por compartir esta obra.

    Un saúdo.

  16.   alexander dixo

    Gustoume moito unha moi boa explicación