Revista Do Linux  
EDIÇÃO DO MÊS
  Perl
  Estudo de Caso
  Delphi para Linux
  Entrevista
  CD do mês
  Programas Matadores
  Interfaces Gráficas
  Hardware
  Segurança
  Expressões Regulares

Expressões regulares
Conhecendo as ferramentas complementares

Na edição número 3 da Revista do Linux, apresentamos uma introdução às Expressões Regulares. Vamos dar continuidade a esse tema, tratando de outras ferramentas (metacaracteres) e dando dicas um pouco mais avançadas.

Primeiramente, vamos fazer uma revisão rápida das ferramentas já vistas:

TABELA 1:
ER casa
. qualquer caractere
[xyz] qualquer das letras dentro dos colchetes
[^xyz] qualquer das letras fora as dentro dos colchetes
[t-z] qualquer das letras entre t e z
z* letra z zero ou mais vezes
z+ letra z uma ou mais vezes

 

Bem, vamos começar a dar nomes aos bois e falar na língua que usuários de ERs entendem. Como já foi visto, o * e o + são quantificadores, pois indicam repetição da entidade anterior. Os [] são chamados de classe de caracteres, e o . é ponto mesmo.

Também foi visto que temos uma classe negada de caracteres, representada por [^] e ainda que podemos ter um intervalo dentro dessa classe, representado por um hífen - entre dois caracteres.

Uma dúvida que deve ter ficado: "e como colocar um ^, - ou ] literal dentro de uma classe de caracteres?". Bem, o ^ só é especial se for o primeiro dentro da classe, então basta colocá-lo em outra posição, como em [a^], que casa ou um a ou um ^. O hífen, basta colocá-lo como primeiro ou último da classe, e o ], ponha-o no início. Assim, [][^-] casa um ], ou [, ou ^ ou -. Olhe de novo a ER, com calma, respire, você vai comprender. &:)

Agora que relembramos as ferramentas já vistas, vamos aumentar nosso arsenal. A primeira novidade é a interrogação ?. Ela também é um quantificador, que casa a entidade anterior zero ou uma vez apenas, ou seja, ela pode ser encarada como opcional, pode existir ou não.

No exercício do artigo anterior, em que se propunha uma ER para casar a palavra "revista" no singular ou plural, simplesmente se faz revistas?.

Sendo a letra s a entidade imediatamente anterior à ?, esta torna-se opcional, atingindo o objetivo.

Com os três quantificadores vistos até então, percebemos que podemos definir com ERs quantidades de 0, 1 ou muitos. Mas e no caso de procurarmos, por exemplo, um número de cinco dígitos? Claro, num primeiro momento, o mais óbvio seria [0-9][0-9][0-9][0-9][0-9]. Funciona, mas além de redundante, como faríamos se fossem quinze, vinte dígitos? Para se ter um controle mais refinado, temos o quantificador numérico: as chaves {}. Dentro delas se coloca a quantidade desejada de ocorrências da entidade anterior. No exemplo anterior do número de cinco dígitos, faríamos [0-9]{5}, ou seja, qualquer número entre 0 e 9, cinco vezes. Atenção aqui, não é o mesmo número repetido como 66666 e sim qualquer número do intervalo, cinco vezes, como 73956 por exemplo.

Mas o quantificador numérico é muito mais flexível que isso, pois além de números fixos de repetições, permite a definição de intervalos, como z{3,5}, que quer dizer: a letra z de três até cinco vezes, o que casaria zzz, zzzz e zzzzz. Além disso, podemos ter uma definição mais relaxada como {,5} e {3,}, que seriam "até 5" e "no mínimo 3", respectivamente.

Dê uma revisada em todos os quantificadores. Leitores mais atentos deverão perceber que os quantificadores *, + e ? são equivalentes a {0,}, {1,} e {0,1}. Pois é. Fazem a mesma coisa, mas os primeiros são mais curtos e fáceis de ler.

Até agora sempre que os quantificadores foram referenciados, se disse que eram relativos à "entidade" anterior. Essa entidade deve-se ao fato de que as ERs podem ser agregadas, ou seja, pode-se concatenar ERs, mesclando ferramentas e construindo-se ERs tão complexas quanto se necessite. Antes de começar a viajar no assunto de ERs agregadas, vamos ver mais uma ferramenta, o agrupamento, com os ().

Como numa expressão matemática, os parênteses definem um grupo, e seu conteúdo pode ser visto como um bloco à parte na expressão. Agora as ERs começam a ficar divertidas. Veja por exemplo (governa)?dor. A "entidade" que a interrogação deixou opcional neste caso foi todo o agrupamento dos parênteses, então essa ER casa governador e dor.

E ainda, como ferramenta complementar ao agrupamento, temos a alternância, representada pela barra vertical |. Seriam alternativas possíveis a uma posição, um "OU" lógico. Assim, vamos fazer uma ER que case algumas possibilidades de cargos públicos que poderíamos ocupar e não nos preocuparmos mais em aprender essas expressões complicadas... comecemos com (governa|sena|verea)dor. sem a ? no grupo, deixamos a dor atrelada aos três cargos públicos de uma só vez: governador, senador e vereador. Mas é claro, não podemos nos esquecer da ala feminina, para empregar a mulher, a irmã... incluiremos um a opcional no final: (governa|sena|verea)dora?. Mas ainda faltam os primos, cunhados e afins, então cargos de vice pra eles:
(vice-)?(governa|sena|verea)dora?. uau! Nossa expressão agora reconhece oito cargos públicos:

QUADRO 1:

governador
governadora
vice-governador
vice-governadora
senador
senadora
vice-senador
vice-senadora
vereador
vereadora
vice-vereador
vice-vereadora

A família toda está garantida &:) Bem, deixando a politicagem de lado, creio que é perceptível o quão poderosa é a sintaxe das ERs, que com poucas ferramentas se consegue ser bem específico, conseguindo dizer muito com pouco.

Mas eu já falei que usando o agrupamento ganha-se um brinde? Não? Pois é, cada vez que se usa os parênteses, seu conteúdo (o que a ER casou) é automaticamente armazenado num registrador interno para poder ser usado mais para a frente na expressão. O nome é feio: referência retroativa, mas essa característica é ótima para procurar coisas repetidas, por exemplo, ao procurar a palavra quero-quero, a ER seria: (quero)-\1. A forma de se referir ao conteúdo do registrador é um número de 1 a 9 com uma barra invertida na frente. Chama-se isso de "número escapado".

Um uso muito comum dessa referência é a procura de palavras repetidas num texto como como estas. Basta a ER ([A-Za-z]+) \1 para encontrá-las, ou seja, qualquer cadeia de letras maiúsculas ou minúsculas seguida de um espaço em branco e seguida da mesma cadeia novamente.

Pode-se fazer uso de até nove registradores sempre contando da esquerda para a direita. Então algo como:

QUADRO 2:

já (vi) o (quero)-\2 (hoje), mas \3 não \1m aqui para vê-lo
é traduzido para "já vi o quero-quero hoje, mas hoje não vim aqui para vê-lo".

Note que os () não alteram o sentido da ER, apenas servem como marcadores. Com isso já demos um grande salto no aprendizado das ERs. A base é isso, o que vem pela frente agora é aplicação disso no mundo real, exemplos práticos, que podem ser executados na linha de comando e detalhes que não são documentados, que só se aprende na prática.

Mencionei que as ERs também podem ser aninhadas? Não? Bom, então essa viagem fica para o próximo artigo...

E como exemplos são melhores que páginas de teoria:

TABELA 2: ER casa as cadeias [ajz] a j z [t-z] t u v w x y z z* <nada> z zz zzz zzzz ... z+ z zz zzz zzzz ... z{2} zz z{2,4} zz zzz zzzz z{,3} <nada> z zz zzz z{3,} zzz zzzz zzzzz ... (a|j)z az jz (aj)* <nada> aj ajaj ajajaj ... [aj]* <nada> a j aa ajjaaj ... (a|j)* <nada> a j aa ajjaaj ... (aj)\1 ajaj .* para pensar com calma
ER casa as cadeias
[ajz] a j z
[t-z] t u v w x y z
z* <nada> z zz zzz zzzz ...
z+ z zz zzz zzzz ...
z{2} zz
zz z{2,4} zz zzz zzzz
z{,3} <nada> z zz zzz
z{3,} zzz zzzz zzzzz ...
(a|j)z az jz
(aj)* nada> aj ajaj ajajaj ...
[aj]* <nada> a j aa ajjaaj ...
(a|j)* <nada> a j aa ajjaaj ...
(aj)\1 ajaj
.* para pensar com calma

  Observação: este último é um ponto chave das ERs, é será abordado em outra edição.

Para saber mais

Mastering Regular Expressions, Jeffrey E. F. Friedl, editora O’Reilly
www1.gve.ch/codeme/cmz/cmzh/node133.html
python.org/doc/howto/regex www.egroups.com/group/sed-br
man 7 regex
man egrep
man awk
man ed

 

A Revista do Linux é editada pela Conectiva S/A
Todos os Direitos Reservados.

Política de Privacidade