Home Map Index Search News Archives Links About LF
[Top Bar]
[Bottom Bar]
[Foto do Autor]
Guido Socher
Sobre o Autor: Amo Linux porque é um sistema gratuito e também é uma diversão trabalhar com pessoas da comunidade de Linux por toda parte do mundo. Meus passatempos preferidos são: escutar os Serviços de Rádio Mundial da BBC, estar com minha namorada, passear de bicicleta pela zona rural e trabalhar com o Linux..

Conteúdo:
Introdução
Um pequeno exemplo
Regras de sintaxe
Expressões regulares para edição de textos

Expressões Regulares

[Illustration]

Abstrato:: expressões regulares que são usadas para contexto avançado em procuras sensíveis e modificações de texto. Eles podem ser achados em muitos editores avançados, e em programas de editoração eletronica e em idiomas.




Introdução

As Expressões Regulares podem ser encontradas em muitos editores como vi, emacs, e em programas como grep, egrep e em linguagens de programação como awk, perl e sed.

As Expressões Regulares são usadas para buscas avançadas dependendo do contexto. Por isso podemos dizer que as Expressões Regulares não são apenas um localizador de cadeias de texto, sim que são a descrição formal de um protetor do texto.

Quando ví pela primeira vez como poderíamos editar textos com a ajuda das Expressões Regulares, fiquei fascinado. Modificações em um texto, para os que os tivesse utilizado durante horas, ficavam prontas em poucos segundos. O que com certeza se veria no monitor, parecia um conjunto de pontos, hífens e outros símbolos. Com certeza alguma coisa estava claro: Queria aprender a linguagem das Expressões Regulares e o que me deixou impressionado, era a facilidade para entender. Segue abaixo, algumas regras de sintaxe muito simples.

Apesar de que as Expressões Regulares estejem muito extendidas no mundo Unix, não existe uma linguagem standard de Expressões Regulares. Mas se bem que poderemos falar de diferentes dialetos. Existem por exemplo dois representantes do conhecido programa grep, egrep e grep. Ambos usam as Expressões Regulares com capacidades ligeiramente diferentes. Perl pode ser qualificada como a linguagem com a sintaxe de Expressões Regulares mais desenvolvida. Com sorte todos estes dialetos seguem os mesmos princípios e no momento em que os entendemos, o resto será fácil.

Neste artigo me dedicarei exclusivamente aos príncipios básicos, os detalhes que poderemos consultar nas páginas dos manuais (man-pages).

Um pequeno exemplo

Suponhamos que tenhamos a seguinte lista de telefones de uma empresa:

Fone Nome ID
     ...
     ...
3412    Bob 123
3834  Jonny 333
1248   Kate 634
1423   Tony 567
2567  Peter 435
3567  Alice 535
1548  Kerry 534
     ...

Estamos tratando com uma empresa com 500 pessoas e os dados estão armazenados em um arquivo ASCII normal. Os registros de pessoas cujo telefone comece com 1, trabalham no edifício 1. Quem trabalha no Edifício 1?


Uma Expressão Regular poderá responder a esta questão:

grep '^1' phonelist.txt

ou

egrep '^1' phonelist.txt

ou

perl -ne 'print if (/^1/)' phonelist.txt

Em palavras normais isto significa: Procura todas as linhas que comecem com um 1. O símbolo "^" é o encarregado de indicar que sómente encontrem os números 1 que se encontrem no príncipio da linha.

Regras de sintaxe

Padrão só com um símbolo

O elemento básico de uma expressão regular é o padrão de só um símbolo. Este padrão sómente é efetivado quando este símbolo puder ser encontrado exatamente como o texto. Um exemplo do que podemos encontrar com o número 1 do exemplo acima.


Outro exemplo para o padrão de só um símbolo

é:

egrep 'Kerry' phonelist.txt

Este padrão se compõe de padrões de só um símbolo (a letra K, e, etc.)

Vários signos podem ser agrupados em um conjunto. Um conjunto é representado com um par de colchetes (o de abrir e o de fechar) e uma lista de caracteres entre eles. Um conjunto também é considerado como um padrão de só um símbolo. A busca deste conjunto se efetivará quando encontramos um e só um dos signos do conjunto do texto. Um exemplo:


[abc]           Um padrão de um só símbolo com o 
                qual poderemos encontrar o símbolo a, b ou c.

[ab0-9]         Um padrão de só um símbolo no qual 
                se procura um a ou um b ou um número
                que se encontre entre o 0 e o 9 no código ASCII.
[a-zA-Z0-9\-]   Este procura uma letra maiúscula ou minúscula
                ou um número ou o signo -.

Numa lista de telefone:
egrep '^1[348]' phonelist.txt

Esta expressão procura linhas que comecem com 13, 14 ou 18.

A maioria dos símbolos ASCII nos leva a uma busca hesitante quando se procura no texto, mas também encontramos símbolos em uma expressão regular que tem um significado especial. Os colchetes até a direita indicam o começo da definição de um conjunto. O símbolo "-" em um conjunto é um símbolo especial e representa uma categoria especial no sistema de símbolos ASCII. Para indicar que nos referimos ao significado normal do símbolo, se coloca uma barra invertida antes "\". Por exemplo, na expressão [a-zA-Z0-9\-]. Em alguns dialetos encontramos que a barra invertida junto a outro símbolo tem um significado especial. Neste caso se obtem o significado normal retirando a barra invertida.

O ponto também é um símbolo importante em uma expressão regular. A busca será efetiva quando o símbolo comparado seja qualquer símbolo menos o símbolo de nova linha do código ASCII. Exemplo:


grep '^.2' phonelist.txt

Esta expressão procura linhas que contenham o número 2 na segunda posição e qualquer outro símbolo antes.

Os pontos podem ser invertidos mediante a colocação de "[^" en lugar de "[" na expressão. Neste caso o símbolo "^" não representa o começo da linha, sim que "[" e "^" juntos representam o inverso do conjunto.


[0-9]    Um padrão de só um símbolo, a procura 
         será efetivada se o símbolo no texto é um número.

[^0-9]   Tudo o que seja um número.

[^abc]   Tudo o que seja um a, b ou c.

.        Tudo menos o símbolo de linha nova. É identico a 
         [^\n]. \n é o símbolo para uma nova linha.


Para procurar todas as línhas que NÃO comecem com um 1, escreveríamos:

egrep '^[^1]' phonelist.txt

Âncoras (anchors)

Antes vimos que "^" representava o início de uma linha. As âncoras são símbolos especiais nas expressões regulares que não demonstram um símbolo e sim uma posição.el inicio de una


^   Inicio de uma linha
$   Final de uma linha

Para encontrar pessoas em nossa lista com um indicativo company-ID) de 567, utilizaremos a expressão:


egrep '567$' phonelist.txt

Significa: Procure linhas que finalizem com 567.

Multiplicadores

Os multiplicadores nos indicam, quantas vezes tem de aparecer um padrão de só um símbolo no texto:

Descriçãogrepegrepperlvivimvile elvisemacs
zero ou mais vezes********
uma ou mais vez\{1,\}++  \+\+\++
zero o uma vez\???  \=\?\=?
de n até m vezes\{n,m\}  {n,m}      \{n,m\}\{n,m\}

Nota: Para os distintos VI teria que utilizar a opção magic.

Um exemplo da lista de telefones:


....
1248   Kate 634
....
1548  Kerry 534
....

Para encontrar uma página que se componha de um 1, vários números, vários espaços e a letra K, escreveríamos:


grep '^1[0-9]\{1,\} \{1,\}K' phonelist.txt
ou utilizaríamos * e repetimos [0-9] e o espaço:
grep '^1[0-9][0-9]*  *K' phonelist.txt
ou
egrep '^1[0-9]+ +K' phonelist.txt
ou
perl -ne 'print if (/^1[0-9]+ +K/)' phonelist.txt

Os multiplicadores nos indicam, quantas vezes tem que aparecer o padrão de só um símbolo que os precede. "23*4" NÃO significa "2, 3, talvéz alguma coisa e depois um 4" (isto seria "23.*4"), senão que significa, que se está buscando "un 2, talvéz alguns 3 e um 4".

É importante saber que um multiplicador é ávido. Isto significa que o primeiro multiplicador se extenderá ao máximo que possa até a direita.

Isto não é muito importante no grep, mas, é importante no momento de editar textos.

A expressão ^1.*4 
se extenderia por toda linha 
1548 Kerry 534
do início até o fim.

A expressão não se extende sómente até a zona curta, o seja, 154, senão até o máximo que possa.

Parenteses como memoria

Os parentesis como memória não influem no tipo ou símbolos que se busca. Servem para que os fragmentos do texto se armazenem e possamos encontrá-los através de variáveis.

O primeiro parentese será referenciado como variável 1, o segundo como variável 2, etc.

Nome do programaSintaxe do parenteseSintaxe das variáveis
grep\(\)\1
egrep()\1
perl()\1 or ${1}
vi,vim,vile,elvis\(\)\1
emacs\(\)\1

Um exemplo:

A expressão [a-z] [a-z]

procura duas letras minúsculas.

Agora podemos utilizar estas variáveis, para procurar padrões de texto como ?otto?:


egrep '([a-z])([a-z])\2\1'
A variável \1 comtém a letra o e \2 a letra t. A expressão serviria também para anna, mas não para yxyx.

Os parenteses não são utilizados normalmente para procura de nomes como otto e anna, senão para editar ou para procurar e substituir.

Uso das Expressões Regulares para o tratamento de Textos

Para editar textos é necessário um editor de textos como vi ou emacs ou perl. Todos estes programas suportam expressões regulares.

No emacs utilizamos M-x query-replace-regexp ou replace-regexp. M-x query-replace-regexp pede confirmação em cada procura e substituição. O mais recomendável é atribuir uma tecla de função ao query-replace ou replace-regexp.

No vi utilizamos :%s/ / /gc. O símbolo % representa a Ex-região ?todo o arquivo? no que podemos recomeçar por qualquer outra Ex-region. No editor vim, por exemplo, podemos marcar uma região com maiúscula-v e o cursor acima/abaixo. Desgraçadamente o artigo sairia de seus propósitos sem que não déssemos uma pequena introdução sobre vim. ///gc é interativo e pede por uma confirmação. s///g não é interativo. No perl utilizamos:

perl -pe 's/ / /g'

Agora alguns exemplos. Na empresa temos que modificar alguns telefones. Todos os telefones que começam com um 1, tem que ter um 2 depois do segundo número. De 1423 passaremos para 14223.


Fone Nome  ID
    ...
3412    Bob 123
3834  Jonny 333
1248   Kate 634
1423   Tony 567
2567  Peter 435
3567  Alice 535
1548  Kerry 534
     ...

e isto é assim de fácil:


vi:    s/^\(1.\)/\12/g
emacs: ^\(1.\)   sustituir por  \12
perl:  perl -pe 's/^(1.)/${1}2/g' phonelist.txt

A lista de telefones aparecerá assim:


Fone Nome  ID
   ...
3412    Bob 123
3834  Jonny 333
12248   Kate 634
14223   Tony 567
2567  Peter 435
3567  Alice 535
15248  Kerry 534
     ...

Perl não sómente conhece as variáveis \1 \9. \12 apontaria para a variável 12. Para solucionar o problema utilizamos simplesmente ${1}.

Mas agora não encontramos as colunas bem alinhadas. Como poderíamos solucionar isto? Poderíamos comprovar se há um espaço na quinta posição e inserir outro.


vi:     s/^\(....\) /\1  /g
emacs:  '^\(....\) '  sustituir por   '\1  '
perl:   perl -pe 's/^(....) /${1}  /g' phonelist.txt

Agora temos:


Fone Nome  ID
    ...
3412     Bob 123
3834   Jonny 333
12248   Kate 634
14223   Tony 567
2567   Peter 435
3567   Alice 535
15248  Karry 534
    ...

Um colega editou a phonelist.txt e não teve o devido cuidado. No princípio de alguma linha encontramos espaços. Como poderemos solucionar?


Fone Nome  ID
    ...
3412     Bob 123
     3834   Jonny 333
12248   Kate 634
14223   Tony 567
 2567   Peter 435
3567   Alice 535
  15248  Kerry 534
     

    ...

Isto terá que solucionar o problema:


vi:     s/^  *//  (existem dois espaços, já que não temos o +)

emacs:  '^ +'  substituir pela cadeia vazia

perl:   perl -pe 's/^ +//' phonelist.txt

Estás escrevendo um programa e utiliza as variáveis temp y temporary. Agora queres substituir a variavel temp pela variável counter. Se utilizasse a opção de procurar e substituir,verias que a variável temporary seria substituida por counterorary. Isto queres evitar.

Com as expressões regularesfaremos bem fácil. Se substituirmos temp([^o]) com counter\1. Com isto, substituiremos temp e não "o". (Outra alternativa seriam as Boundaries, que não foi comentada aqui.)

Espero que este artigo tenha despertado sua curiosidade. Se desejas continuar, sugiro consultar as man-pages de teu editor preferido.

Existem mais símbolos especiais nas expressões regulares, como por exemplo, Alterations, Art Order, e naturalmente as Boundaries.

Que disfrutes então


Este website é mantido por Miguel Angel Sepulveda
© Guido Socher 1998
LinuxFocus 1998