Anda di halaman 1dari 17

Conhecendo as Expresses Regulares

Aurlio Marinho Jargas http://aurelio.net

Abril de 2004

ndice
Sobre o Curso...........................................................................................................1 Introduo ..................................................................................................................2 O ambiente de testes................................................................................................3 Conhecendo o arquivo /etc/passwd..................................................................3 Conhecendo o comando grep...........................................................................4 Conhecendo cada um dos metacaracteres............................................................5 O circunflexo ^ ...................................................................................................5 O cifro $ ...........................................................................................................5 A lista [].............................................................................................................6 O ponto ............................................................................................................7 As chaves {}......................................................................................................8 O curinga .* (AND)............................................................................................9 O ou | (OR) ......................................................................................................10 Os outros repetidores: ? * +............................................................................10 A lista negada [^].............................................................................................10 O intervalo em listas [] ..................................................................................11 . A tabela ASCII .........................................................................................................12 . A tabela dos metacaracteres.................................................................................13 Escapar ou no escapar? .......................................................................................14 Para saber mais .......................................................................................................15

Sobre o Curso
Nome Conhecendo as Expresses Regulares Instrutor Aurlio Marinho Jargas (http://aurelio.net) Objetivo Desmistificar e ensinar aos alunos todos os metacaracteres bsicos, preparandoos para comporem suas prprias expresses. PrRequisitos Noes bsicas de informtica e operao do sistema pela linha de comando. Pblico Alvo Desenvolvedores, administradores de sistemas, programadores e interessados em geral. Durao 8 horas

Introduo
Expresses Regulares. Um assunto que muitos torcem o nariz ao ouvir falar, mas que sempre acaba aparecendo na resoluo dos mais diversos problemas. Para quem no conhece ou no domina o assunto, difcil perceber a utilidade de saber escrever todos aqueles smbolos estranhos. Mas medida que vai se aprendendo, aplicando, tudo comea a clarear. Este minicurso apresentar os componentes utilizados nas expresses e ensinar como utilizlos. Uma Expresso Regular (ER) um mtodo formal de se especificar um padro de texto. uma composio de smbolos, caracteres com funes especiais, chamados "metacaracteres" que, agrupados entre si e com caracteres literais, formam uma seqncia, uma expresso. Essa expresso testada em textos e retorna sucesso caso esse texto obedea exatamente a todas as suas condies. Dizse que o texto "casou" com a expresso. A ERs servem para se dizer algo abrangente de forma especfica. Definido o padro de busca, temse uma lista (finita ou no) de possibilidades de casamento. Em um exemplo rpido, [rgp]ato pode casar "rato", "gato" e "pato". As ERs so teis para buscar ou validar textos variveis como: data horrio nmero IP endereo de email endereo de Internet declarao de uma funo() dados na coluna N de um texto dados que esto entre <tags></tags> nmero de telefone, RG, CPF, carto de crdito Vrios editores de texto e linguagens de programao tm suporte a ERs, ento o tempo investido em seu aprendizado recompensado pela larga variedade de aplicativos onde ele pode ser praticado.

O ambiente de testes
Para conhecer e desvendar os segredos das Expresses Regulares, usaremos o comando grep, que serve para "pescar" linhas dentro de um texto. Voc informa uma palavra e o grep retorna todas as linhas do texto em que ele encontrar essa palavra.

Conhecendo o arquivo /etc/passwd


O arquivo de dados que usaremos nos testes ser o /etc/passwd, a base de usurios de um sistema UNIX/Linux. Ento, primeiro vamos conhecer o que tem dentro desse tal passwd:
$ cat /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin news:x:9:13:news:/etc/news: uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin gopher:x:13:30:gopher:/var/gopher:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin ntp:x:38:38::/etc/ntp:/sbin/nologin mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash carlos:x:500:500:carlos:/home/carlos:/bin/bash ana:x:501:501:Ana Paula Moreira:/home/ana:/bin/bash acs:x:502:502:Antonio Carlos Silva:/home/acs:/bin/bash $

So vrias linhas, uma para cada usurio. O separador de informaes o caractere doispontos ":" e cada linha possui sete campos, no seguinte formato:
login : senha : UID : GID : Nome Completo : Diretrio $HOME : shell

Todas as senhas esto protegidas em outro arquivo, por isso h somente uma letra "x" em seu lugar. Analisando a primeira linha, sabemos que ela referente ao administrador do sistema ("root"). Seu nmero de usurio (UID) e seu nmero de grupo so iguais: zero. Seu nome "root" mesmo, seu diretrio padro o "/root" e seu shell de login "bash".

Conhecendo o comando grep


Para no precisar listar o contedo do arquivo todo para saber os dados do usurio "root", podemos usar o grep para pesquisar e nos retornar somente a linha dele. O formato do comando grep o seguinte:
grep PALAVRA ARQUIVO

simples, basta passar a palavra desejada e o nome do arquivo aonde procurar por ela. Como queremos "pescar" somente a linha do usurio root, basta fazer:
$ grep root /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin $

Epa! Alm da linha do root, o grep retornou tambm a linha do usurio "operator". Mas por que isso se a pesquisa era somente por "root"? Olhando mais atentamente para a linha do usurio operator, vemos que o seu diretrio $HOME "/root". Como dissemos ao grep "procure por root", as duas linhas so resultados vlidos. Para obter somente a linha desejada, seria preciso haver uma maneira de dizer ao grep "procure por root no incio da linha". neste momento que as Expresses Regulares entram em cena. Alm de palavras, o grep tambm entende ERs. Uma expresso formada por caracteres normais que formam palavras (letras e nmeros) como "root", mas tambm por smbolos especais, os chamados metacaracteres.

Conhecendo cada um dos metacaracteres


Cada metacaractere uma ferramenta que tem uma funo especfica. Eles servem para dar mais poder s pesquisas, informando padres e posies impossveis de se especificar usando somente caracteres normais. Os metacaracteres so pequenos pedacinhos simples que agrupados entre si, ou com caracteres normais, formam algo maior, uma expresso. O importante compreender bem cada um individualmente, e depois apenas llos em seqncia.

O circunflexo ^
O primeiro metacaractere que veremos o circunflexo "^" (ou chapuzinho), que simboliza o incio de uma linha. Podemos uslo para resolver o problema anterior de obter somente a linha do usurio root:
$ grep ^root /etc/passwd root:x:0:0:root:/root:/bin/bash $

Funcionou! Reveja o que acabamos de fazer: passamos ao grep uma Expresso Regular composta pelo metacaractere circunflexo, seguido da palavra "root". No confunda, no procuramos pelo texto "^root", mas sim pela palavra "root" no incio da linha. Que diferena faz um simples ^ hein?

O cifro $
O circunflexo chamado de metacaractere de posicionamento, pois representa uma posio especfica da linha. Seu primo o cifro "$", que representa o fim de uma linha. Lembra que o ltimo campo de cada linha do arquivo "passwd" o shell de login do usurio? Agora com o metacaractere cifro podemos pesquisar todos os usurios, alm do root, que usam o "bash" como shell:
$ grep bash$ /etc/passwd root:x:0:0:root:/root:/bin/bash mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash carlos:x:500:500:carlos:/home/carlos:/bin/bash ana:x:501:501:Ana Paula Moreira:/home/ana:/bin/bash acs:x:502:502:Antonio Carlos Silva:/home/acs:/bin/bash $

A Expresso Regular "bash$" procura pela palavra "bash" no final da linha. Ou ainda, a palavra "bash" seguida de um fim de linha. Esse cifro o mesmo caractere que utilizado para identificar as variveis do shell, como $PWD e $HOME. Para evitar possveis problemas com a expanso de variveis, preciso "proteger" a Expresso Regular passada ao grep. A proteo feita se colocando a ER entre 'aspas simples'. Isso evitar muitas dores de cabea. Dica n1: No shell, sempre proteja as ERs com 'aspas simples' O comando anterior, agora 'aspeado', fica:
$ grep 'bash$' /etc/passwd

Juntando os dois metacaracteres j vistos, temos na mo uma ER muito til que serve para encontrar linhas em branco:
^$

O que uma linha em branco seno um comeo de linha seguido de um fim de linha? Guarde essa ER num cantinho especial de sua memria, pois comum precisar dela nos problemas do dia a dia. Mas como nem s de comeo e fim de linha so compostos os problemas, precisamos conhecer os outros metacaracteres disponveis.

A lista []
Mudando um pouco de tarefa, que tal pesquisar os usurios que possuem o nome "Carlos"? No arquivo de exemplo h dois, o "carlos" e o "acs". Vamos tentar obter ambos com o grep:
$ grep 'carlos' /etc/passwd carlos:x:500:500:carlos:/home/carlos:/bin/bash $ grep 'Carlos' /etc/passwd acs:x:502:502:Antonio Carlos Silva:/home/acs:/bin/bash $

Puxa vida... Um est em minsculas e o outro com a primeira letra maiscula, sendo preciso usar o grep duas vezes para extralos. Para resolver este problema com apenas um comando, novamente precisaremos dos poderes das Expresses Regulares! O terceiro metacaractere que veremos a "lista". Basta colocar entre colchetes "[]" todos os caracteres que podem aparecer em uma determinada posio. Podem ser
6

tantos quantos se precise, mas em nosso caso apenas dois bastam, "C" e "c":
$ grep '[Cc]arlos' /etc/passwd carlos:x:500:500:carlos:/home/carlos:/bin/bash acs:x:502:502:Antonio Carlos Silva:/home/acs:/bin/bash $

Repare bem no detalhe, toda a "lista" (os colchetes e seu contedo) vale para apenas uma posio, um caractere. A ER "[Cc]arlos" serve para pesquisar por "Carlos" e "carlos" ao mesmo tempo. Dica n2: A lista, por maior que seja, representa apenas um caractere Podemos combinar a lista com um dos metacaracteres j vistos, produzindo uma ER mais poderosa:
$ grep '^[aeiou]' /etc/passwd adm:x:3:4:adm:/var/adm:/sbin/nologin uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin ana:x:501:501:Ana Paula Moreira:/home/ana:/bin/bash acs:x:502:502:Antonio Carlos Silva:/home/acs:/bin/bash $

Este comando procura por usurios cujo login comece com uma vogal! Note o uso do circunflexo para "amarrar" a pesquisa no incio da linha. Traduzindo essa ER, fica: busque por linhas que comeam com a letra "a", ou "e", ou "i" ou "o" ou "u". Para fazer o inverso e buscar as linhas que comeam com consoantes, a ER fica bem mais comprida, pois necessrio especificar todas as letras:
$ grep '^[bcdfghjklmnpqrstvwxyz]' /etc/passwd

O ponto .
s vezes, necessrio permitir "qualquer" caractere numa certa posio. Por exemplo, para procurar usurios onde a segunda letra do login seja uma vogal, como "mario", e "jose", mas no "ana". No importa qual a primeira letra, pode ser qualquer uma, mas a segunda deve ser uma vogal. O ponto o metacaractere que significa "qualquer letra". E mais, na verdade ele significa "qualquer caractere", pois alm de letras ele pode representar um nmero, um smbolo, um TAB, enfim: qualquer caractere.
$ grep '^.[aeiou]' /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin news:x:9:13:news:/etc/news: uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin gopher:x:13:30:gopher:/var/gopher:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin carlos:x:500:500:carlos:/home/carlos:/bin/bash $

Esta expresso diz: " partir do comeo da linha, procure qualquer caractere seguido de uma vogal". O ponto tambm pode ser usado para se procurar por linhas de um tamanho fixo, independente do seu contedo. Que tal se obter apenas as linhas que possuam exatamente 27 caracteres?
$ grep '^...........................$' /etc/passwd news:x:9:13:news:/etc/news: $

Ser que ali tem 27 pontos mesmo? Como saber ao certo? Estranho isso de ficar colocando vrios pontinhos n?

As chaves {}
Como Expresses Regulares so bacanas, elas facilitam este tipo de tarefa tambm. Colocando um nmero entre chaves "{}", indicase uma quantidade de repeties do caractere (ou metacaractere) anterior:
$ egrep '^.{27}$' passwd news:x:9:13:news:/etc/news: $

Essa expresso faz o mesmo que a anterior: procura por linhas que tenham 27 caracteres, quaisquer que sejam eles. A vantagem que basta olhar o nmero de repeties, no precisa ficar contando os pontinhos. Dica n3: .{27} igual a 27 pontos! Note que foi usado o egrep e no o grep. porque as chaves fazem parte de um conjunto avanado de Expresses Regulares ("extended"), ento o egrep lida melhor com elas. Se fosse para usar o grep normal, teria que "escapar" as chaves:
$ grep '^.\{27\}$' /etc/passwd

Feio! Vamos usar somente o egrep daqui pra frente para evitar tais escapes. As chaves ainda aceitam intervalos, sendo possvel informar uma faixa de repeties vlidas, com mnimo e mximo. Para procurar por linhas que tenham de 20 a 40 caracteres:
$ egrep '^.{20,40}$' /etc/passwd

Se omitir o segundo nmero e manter a vrgula, fica uma faixa aberta, sem fim. Assim pode se informar repeties de "no mnimo N vezes". Para obter as linhas que possuem 40 caracteres ou mais:
$ egrep '^.{40,}$' /etc/passwd

E claro, essa repetio tambm pode ser usada para caracteres comuns ou outros metacaracteres alm do ponto. Que tal repetir uma lista? Um bom exemplo procurar os usurios que tm um UID ou GID de trs dgitos ou mais:
$ egrep '[0123456789]{3,}' /etc/passwd games:x:12:100:games:/usr/games:/sbin/nologin carlos:x:500:500:carlos:/home/carlos:/bin/bash ana:x:501:501:Ana Paula Moreira:/home/ana:/bin/bash acs:x:502:502:Antonio Carlos Silva:/home/acs:/bin/bash $

Nesse exemplo a ER pesquisou por "qualquer nmero repetido no mnimo trs vezes", ou seja, com um mnimo de trs dgitos.

O curinga .* (AND)
Quando se procura por dois trechos especficos numa mesma linha, no importando o que h entre eles, usase o curinga ".*" para significar "qualquer coisa". Um exemplo procurar os usurios que comeam com vogais e usam o shell bash:
$ egrep '^[aeiou].*bash$' /etc/passwd ana:x:501:501:Ana Paula Moreira:/home/ana:/bin/bash acs:x:502:502:Antonio Carlos Silva:/home/acs:/bin/bash $

Ou seja, procuramos por uma linha que comece com uma vogal e termine com a palavra "bash", no importando o que tem no meio, pode ser qualquer coisa. Essa ER funcionou mais ou menos como um AND lgico, onde s casa se tiver as duas pesquisas. Dica n4: .* qualquer coisa, inclusive nada
9

O ou | (OR)
Para fazer o OR lgico, onde se procura por uma coisa ou outra, devese usar o pipe "|" e delimitar as opes com os parnteses "()":
$ egrep '^(ana|carlos|acs):' /etc/passwd carlos:x:500:500:carlos:/home/carlos:/bin/bash ana:x:501:501:Ana Paula Moreira:/home/ana:/bin/bash acs:x:502:502:Antonio Carlos Silva:/home/acs:/bin/bash $

Essa ER casa apenas as linhas dos trs usurios citados. Ela comea procurando no incio da linha "^", depois procura ou a palavra "ana", ou a palavra "carlos", ou a palavra "acs", seguido pelo doispontos.

Os outros repetidores: ? * +
Outros metacaracteres que podem ser usados so o asterisco, o mais e a interrogao (chamado opcional). Eles definem quantidades e funcionam como as chaves, porm com uma sintaxe mais prtica: Meta ? * + Nome opcional asterisco mais Equivalente {0,1} {0,} {1,} Descrio Pode aparecer ou no (opcional) Pode aparecer em qualquer quantidade Deve aparecer no mnimo uma vez

A lista negada [^]


Ainda temos mais detalhes para ver nas listas! Lembra do comando para pesquisar os usurios que iniciam o login com consoantes?
$ grep '^[bcdfghjklmnpqrstvwxyz]' /etc/passwd

Como incmodo ter que colocar todas essas letras, tambm possvel "negar" uma lista, especificando quais os caracteres que no so vlidos em uma posio. Assim, para buscar as consoantes, podemos dizer "busque por linhas que no comecem com vogais":
$ grep '^[^aeiou]' /etc/passwd

10

Veja como negar uma lista fcil! Caso o primeiro caractere dentro dos colchetes seja um circunflexo, ele inverter o sentido dessa lista, tornandoa uma "lista negada". Ela casar qualquer caractere, EXCETO os listados aps o "^". Mas tenha cuidado, use a lista negada com cautela. Negar alguns caracteres significa permitir todos os outros! Nmeros, smbolos, TAB e espao em branco tambm fazem parte de "qualquer caractere exceto vogais". Em nosso exemplo atual isso no atrapalha, mas tenha sempre em mente que essa negao bem abrangente. Dica n5: Ateno, negar uma lista significa permitir "todo o resto"

O intervalo em listas []
Outra facilidade da lista a possibilidade de se indicar intervalos, faixas. Basta colocar um hfen entre duas letras que ele ser expandido para todas as letras existentes no intervalo. Por exemplo "af" interpretado como "todas as letras entre a e f, inclusive", ou seja "abcdef". Reescrevendo o exemplo de procurar por nmeros de trs dgitos ou mais, que tinha sido:
$ egrep '[0123456789]{3,}' /etc/passwd

Agora fica:
$ egrep '[09]{3,}' /etc/passwd

Alm de letras e nmeros, o intervalo funciona para smbolos e outros caracteres. A ordem "oficial" a ordem que os caracteres ocupam na tabela ASCII. Dica n6: [09] o mesmo que [0123456789]

11

A tabela ASCII
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 ! " # $ % & ' ( ) * + , . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 161 ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 o 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255

Na dvida, basta consultar essa tabela para ver quais so os caracteres de determinado intervalo. Por exemplo, o intervalo "[:@]" engloba os caracteres : ; < = > ? @. Na tabela, tambm podemos ver que o intervalo "az" no inclui os caracteres acentuados! Para procurar por letras minsculas num texto em portugus, devese fazer "[az]".

12

A tabela dos metacaracteres


Meta ^ $ Nome Posicionamento circunflexo Representa o comeo da linha cifro Representa o fim da linha Texto [abc] [ad] [^abc] (esse|aquele) lista lista Casa as letras 'a' ou 'b' ou 'c' Casa as letras 'a' ou 'b' ou 'c' ou 'd'

lista negada Casa qualquer caractere, exceto 'a', 'b' e 'c' ou Casa as palavras 'esse' ou 'aquele' Quantidade I

a{2} a{2,4} a{2,}

chaves chaves chaves

Casa a letra 'a' duas vezes Casa a letra 'a' de duas a quatro vezes Casa a letra 'a' no mnimo duas vezes Quantidade II

a? a* a+

opcional asterisco mais

Casa a letra 'a' zero ou uma vezes Casa a letra 'a' zero ou mais vezes Casa a letra 'a' uma ou mais vezes Curingas

. .*

ponto curinga

Casa um caractere qualquer Casa qualquer coisa, o tudo e o nada

Ateno: No confundir os metacaracteres com os curingas do shell. Na linha de comando usase "*.txt", "arquivo??.txt" e "arquivo.{txt,html}" para expressar mais de um arquivo. Estes so curingas, e no metacaracteres. H uma similaridade e equivalncia entre as aes, mas ERs so usadas em programas como grep, sed e awk, e os curingas so usados na linha de comando, para expandir nomes de arquivos. Shell ERs * ? .* .

{,} (|)
13

Escapar ou no escapar?
Dependendo do aplicativo, a sintaxe das ERs pode ser diferente da do egrep. No sed e awk por exemplo (bem como no grep), as chaves e o "ou" devem ser escapados para serem especiais. Infelizmente a implementao de Expresses Regulares pelos programas uma selva, e no tem como fugir do decoreba dessa tabela: Programa opc mais chaves borda ou grupo awk egrep emacs find gawk grep sed vim ? ? ? ? ? \? \? \= + + + + + \+ \+ \+ {,} {,} \{,\} \{,\} \{,} \b \b \b \<\> \b \<\> \<\> | | \| \| | \| \| \| () () \(\) \(\) () \(\) \(\) \(\)

14

Para saber mais


H programas para auxiliar o aprendizado de Expresses Regulares. O txt2regex (http://txt2regex.sourceforge.net) um programa modo texto que constri ERs apenas mostrando menus (em portugus) ao usurio, que escolhe o que quer. J para a interface grfica, tem o Regex Coach (http://www.weitz.de/regexcoach/), com verses para Linux e Windows. Para aprofundarse no assunto, leia o livro "Expresses Regulares", disponvel online em http://aurelio.net/er. A lista de discusso sedbr um lugar onde dvidas podem ser tiradas: http://br.groups.yahoo.com/group/sedbr.

15