Perl Brasil

Pesquisar

Documentação

Planeta

Eventos

Comunidade

r9 - 31 May 2008 - MarcoLima


NOME

perlrequick - Introdução rápida às expressões regulares em Perl (EM TRADUÇÃO)

voltar para o topo


DESCRIÇÃO

Este documento cobre os aspectos básicos para entendendimento, criação e uso de expressões regulares ('regexes') em Perl.

voltar para o topo


O Guia

Combinação de uma palavra simples

A expressão regular mais simples é uma simples palavra ou, mais usualmente, uma string de caracteres. Uma regex consiste em combinar uma palavra com alguma string que contenha aquela palavra:
    "Hello World" =~ /World/;  # combina
Nesta expressão, World é uma regex e o delimitador // que envolve World diz ao perl para procurar uma string para uma combinação. O operador =~ associa a string com a regex a ser combinada e retorna um valor verdadeiro se a regex combinar com a string, ou falso se a regex não combinar. Em nosso caso, World combina com a segunda palavra em "Hello World", então a expressão é verdadeira. Esta idéia tem diversas variações. Expressões como esta são convenientes em condicionais:
    print "It matches\n" if "Hello World" =~ /World/;
O sentido da combinação pode ser invertido usando-se o operador !~:
    print "It doesn't match\n" if "Hello World" !~ /World/;
A string literal na regex pode ser substituída por uma variável:
    $greeting = "World";
    print "It matches\n" if "Hello World" =~ /$greeting/;
Se você está combinando em comparação com $_, o trecho $_ =~ pode ser omitido:
    $_ = "Hello World";
    print "It matches\n" if /World/;
Finalmente, o delimitador default // para uma combinação pode ser trocado por delimitadores arbitrários colocando-se um 'm' na frente:
    "Hello World" =~ m!World!;   # combina, delimitado por '!'
    "Hello World" =~ m{World};   # combina, note o delimitador '{}'
    "/usr/bin/perl" =~ m"/perl"; # combina após '/usr/bin',
                                 # '/' tornou-se um caracter comum
Regexes podem combinar uma parte específica da string a fim de que a expressão seja verdadeira:
    "Hello World" =~ /world/;  # não combina, case sensitive
    "Hello World" =~ /o W/;    # combina, ' ' é um caracter comum
    "Hello World" =~ /World /; # não combina, não contém ' ' no final
perl sempre combinará no ponto mais imediato possível da string:
    "Hello World" =~ /o/;       # combina o 'o' em 'Hello'
    "That hat is red" =~ /hat/; # combina 'hat' em That
Nem todos os caracteres podem ser usados estritamente com são em uma combinação. Alguns caracteres, chamados de metacaracteres, são reservados para o uso na notação em regex. Os metacaracteres são:
    {}[]()^$.|*+?\
Um metacaracter pode ser combinado pela adição de uma contrabarra (escape) antes dele:
    "2+2=4" =~ /2+2/;    # não combina, + é um metacaracter
    "2+2=4" =~ /2\+2/;   #combina, \+ é tratado como um + comum
    'C:\WIN32' =~ /C:\\WIN/;                       # combina
    "/usr/bin/perl" =~ /\/usr\/bin\/perl/;  # combina
Na última regex, a barra '/' também recebe uma contrabarra uma vez que é usada para delimitar a regex. Caracteres ASCII não-imprimíveis são representados por seqüências de escapes. Exemplos comuns são \t para uma tabulação, \n para uma quebra de linha, e \r para o retorno de carro. Bytes arbitrários são representados pela seqüência de escape para octal, isto é, \033, ou seqüência de escape para hexadecimal, isto é, \x1B.
    "1000\t2000" =~ m(0\t2)        # combina
    "cat"        =~ /\143\x61\x74/ # combina, mas um estranho caminho para se soletrar cat
Regexes são, em sua maioria, tratadas como strings de aspas duplas, logo a substituição de variáveis funciona:
    $foo = 'house';
    'cathouse' =~ /cat$foo/;   # combina
    'housecat' =~ /${foo}cat/; # combina
Com tudo de regexes acima mencionado, se a regex combinou em algum lugar na string, ela foi considerada uma combinação. Para especificar onde ela deveria combinar, nos usaríamos os metacaracteres âncoras ^ e $. A âncora ^ significa combinar no início da string e a âncora $ significa combinar no fim da string, ou antes de uma quebra de linha no fim da string. Alguns exemplos:
    "housekeeper" =~ /keeper/;         # combina
    "housekeeper" =~ /^keeper/;        # não combina
    "housekeeper" =~ /keeper$/;        # combina
    "housekeeper\n" =~ /keeper$/;      # combina
    "housekeeper" =~ /^housekeeper$/;  # combina

Usando classes de caracteres

Uma classe de caracter admite um conjunto de caracteres possíveis, ao invés de apenas um caracter simples, para combinar em um ponto particular na regex. Classes de caractere são denotadas por colchetes [...], com o conjunto de possíveis caracteres a serem combinados dentro. Aqui estão alguns exemplos:
    /cat/;            # combina 'cat'
    /[bcr]at/;        # combina 'bat', 'cat', or 'rat'
    "abc" =~ /[cab]/; # combina 'a'
Na última expressão, embora 'c' seja o primeiro caracter na classe, o ponto mais imediato no qual a regex pode combinar é 'a'.
    /[yY][eE][sS]/; # combina 'yes' no modo case-insensitive
                    # 'yes', 'Yes', 'YES', etc.
    /yes/i;         # também combina 'yes' no modo case-insensitive
O último exemplo mostra uma combinação com um modificador 'i', o qual efetua a combinação case-insensitive. Classes de caracteres também têm caracteres comuns e especiais, mas os conjuntos de caracteres comuns e especiais dentro de uma classe de caracter são diferentes daqueles fora da classe de caracteres. Os caracteres especiais para a classe de caracteres são -]\^$ e são combinados usando um escape:
   /[\]c]def/; # combina']def' ou 'cdef'
   $x = 'bcr';
   /[$x]at/;   # combina 'bat, 'cat', ou 'rat'
   /[\$x]at/;  # combina '$at' ou 'xat'
   /[\\$x]at/; # combina '\at', 'bat, 'cat', ou 'rat'
O caracter especial '-' age como um operador de intervalo dentro da classe de caracteres, logo aquele desajeitado [0123456789] e [abc...xyz] torna-se o elegante [0-9] e [a-z]:
    /item[0-9]/;  # combina 'item0' ou ... ou 'item9'
    /[0-9a-fA-F]/;  # combina um dígito hexadecimal
Se '-' é o primeiro ou o último caracter na classe de caracteres, ele é tratado como um caracter comum. O caracter especial ^ na primeira posição de um classe de caracteres denota uma classe de caracter negada, o qual combina algum caracter exceto aqueles nos colchetes. Ambos [...] e [^...] devem combinar um caracter, ou a combinação falha. Então
    /[^a]at/;  # não combina 'aat' ou 'at', mas combina
               # todos os outros 'bat', 'cat, '0at', '%at', etc.
    /[^0-9]/;  # combina um caracter não-numérico
    /[a^]at/;  # combina 'aat' ou '^at'; aqui '^' é comum
Perl tem várias abreviações para classes de caracteres comuns: As abreviações \d\s\w\D\S\W podem ser usadas dentro e fora das classes de caracteres. Aqui estão algumas em uso:
    /\d\d:\d\d:\d\d/; # combina um formato de tempo hh:mm:ss
    /[\d\s]/;         # combina algum dígito ou caracter de espaço em branco
    /\w\W\w/;         # combina um caracter de palavra, seguido por um
                      # caracter não de palavra, seguido por um caracter de palavra
    /..rt/;           # combina quaisquer dois caracteres, seguidos por 'rt'
    /end\./;          # combina 'end.'
    /end[.]/;         # alguma coisa, combina 'end.'
A palavra âncora \b combina um limite entre um caracter de palavara e um caracter não de palavra \w\W ou \W\w:
    $x = "Housecat catenates house and cat";
    $x =~ /\bcat/;  # combina cat em 'catenates'
    $x =~ /cat\b/;  # combina cat em 'housecat'
    $x =~ /\bcat\b/;  # combina 'cat' no final da string
No último exemplo, o fim da string é considerado um caracter limite.

Combinando isto ou aquilo

Nós podemos combinar diferentes strings de caracteres com o metacaracter de alternância '|'. Para combinar dog ou cat, nós formamos a regex dog|cat. Como antes, perl tentará combinar a regex no ponto mais imediato possível da string. Em cada posição de caracter, perl primeiro tentará combinar a primeira alternativa, dog. Se dog não combinar, perl tentará então a próxima alternativa, cat. Se cat também não combinar, então a combinação falha e perl move para a próxima posição na string. Alguns exemplos:
    "cats and dogs" =~ /cat|dog|bird/;  # combina "cat"
    "cats and dogs" =~ /dog|cat|bird/;  # combina "cat"
Embora dog seja a primeira alternativa na segunda regex, cat está apto a combinar mais cedo na string:
    "cats"          =~ /c|ca|cat|cats/; # combina "c"
    "cats"          =~ /cats|cat|ca|c/; # combina "cats"
Em uma dada posição de caracter, a primeira alternativa que possibilita a regex combinar para ter sucesso será a que combina. Aqui, todas as alternativas combinam na primeira posição da string, logo a primeira combina.

Agrupando coisas e combinando hierarquicamente

O metacaracter de agrupamento () permite que uma parte da regex seja tratada como uma unidade simples. Partes da regex são agrupadas pela inclusão delas entre parênteses. A regex house(cat|keeper) significa combinar house seguida por ou cat ou keeper. Mais alguns exemplos são
    /(a|b)b/;    # combina 'ab' ou 'bb'
    /(^a|b)c/;   # combina 'ac' no início da string ou 'bc' em qualquer lugar
    /house(cat|)/;  # combina ou 'housecat' ou 'house'
    /house(cat(s|)|)/;  # combina ou 'housecats' ou 'housecat' ou
                        # 'house'.  Note que agrupamentos podem ser aninhados.
    "20" =~ /(19|20|)\d\d/;  # combina a alternativa nula '()\d\d',
                             # porque '20\d\d' não pode combinar

Extraindo combinações

Os metacaracteres de agrupamento () também permitem a extração de partes da string combinada. Para cada agrupamento, a parte interna que foi combinada vai para dentro das variáveis especiais $1, $2, etc. Elas podem ser usadas apenas como variáveis comuns:
    # extrai horas, minutos, segundos
    $time =~ /(\d\d):(\d\d):(\d\d)/;  # combina o formato hh:mm:ss
    $hours = $1;
    $minutes = $2;
    $seconds = $3;
No contexto de lista, uma combinação /regex/ com agrupamentos retornará a lista de valores combinados ($1,$2,...). Assim nós poderíamos reescrevê-la como
    ($hours, $minutes, $second) = ($time =~ /(\d\d):(\d\d):(\d\d)/);
Se os agrupamentos em uma regex estão aninhados, $1 captura o grupo com o parêntesis aberto mais à esquerda, $2 o próximo parêntesis aberto, etc. Por exemplo, aqui está uma regex complexa e as variáveis de captura indicadas abaixo:
    /(ab(cd|ef)((gi)|j))/;
     1  2      34
Associadas às variáveis de captura $1, $2, ... estão as retro-referências \1, \2, ... Retro-referências são variáveis de captura que podem ser usadas dentro de uma regex:
    /(\w\w\w)\s\1/; # encontra seqüências como 'the the' na string
$1, $2, ... deveriam ser usadas somente fora de uma regex, e \1, \2, ... somente dentro de uma regex.

Repetições de Combinações

Os metacaracteres quantificadores ?, *, +, e {} permitem-nos determinar o número de repetições de um trecho de uma regex que nós consideramos ser uma combinação. Quantificadores são colocados imediatamente depois de um caracter, classes de caracter ou agrupamento que nós queremos especificar. Eles têm o seguinte significado: Aqui estão alguns exemplos:
    /[a-z]+\s+\d*/;  # combina uma palavra com letras minúsculas, pelo menos um espaço e
                     # qualquer número de dígitos
    /(\w+)\s+\1/;    # combina palavras duplicadas de tamanho arbitrário
    $year =~ /\d{2,4}/;  # certifica-se de que o ano seja de pelo menos 2 porém não mais
                         # que 4 dígitos
    $year =~ /\d{4}|\d{2}/;    # melhor combinação; descarta datas de 3 dígitos
Estes quantificadores tentarão combinar o quanto for possível da string, enquanto a regex estiver permitindo combinar. Logo nós temos
    $x = 'the cat in the hat';
    $x =~ /^(.*)(at)(.*)$/; # combina,
                            # $1 = 'the cat in the h'
                            # $2 = 'at'
                            # $3 = ''   (0 combinações)
O primeiro quantificador .* captura o quanto for possível das string enquanto a regex estiver tentando combinar. O segundo quantificador .* não tem string à esquerda dele, logo ele combina 0 vezes.

Mais combinações

Existem poucas coisas que você pode querer saber sobre operadores de combinação. No código
    $pattern = 'Seuss';
    while (<>) {
        print if /$pattern/;
    }
perl reavalia $pattern cada vez até o fim do loop. Se $pattern não estiver modificando, use o modificador //o, para executar a substituição de variáveis somente uma vez. Se você não quiser alguma substituição em tudo, use o delimitador especial m'':
    @pattern = ('Seuss');
    m/@pattern/; # combina 'Seuss'
    m'@pattern'; # combina a string literal '@pattern'
O modificador global //g permite que o operador de combinação combine dentro de uma string quantas vezes for possível. No contexto de escalar, sucessivas combinações em comparação com uma string terão //g saltanto de combinação em combinação, conservando o caminho de posições na string conforme elas ocorrem ao seu comprimento. Você pode obter ou definir as posições com a função pos(). Por exemplo,
    $x = "cat dog house"; # 3 palavras
    while ($x =~ /(\w+)/g) {
        print "Word is $1, ends at position ", pos $x, "\n";
    }
imprime
    Word is cat, ends at position 3
    Word is dog, ends at position 7
    Word is house, ends at position 13
Uma combinação reprovada ou uma troca da string alvo reinicializam as posições. Se você não deseja que as posições sejam zeradas após uma falha nas combinções, acrescente o //c, como em /regex/gc. No contexto de lista, //g retorna uma lista de agrupamentos combinados, ou se não existem agrupamentos, uma lista de combinações para a regex inteira. Então
    @words = ($x =~ /(\w+)/g);  # combina,
                                # $word[0] = 'cat'
                                # $word[1] = 'dog'
                                # $word[2] = 'house'

Pesquisar e substituir

Pesquisa e substituição são executadas usando-se s/regex/substituição/modificadores. A substituição é uma string Perl com aspas duplas que substitui na string o que quer que seja combinado com o a regex. O operador =~ é também usado para associar a string com s///. Se a combinação for em comparação com $_, o $_ =~  pode ser desconsiderado. Se existe uma combinação, s/// retorna o número de substituições feitas, caso contrário ele retorna falso. Aqui estão uns poucos exemplos:
    $x = "Time to feed the cat!";
    $x =~ s/cat/hacker/;   # $x contém  "Time to feed the hacker!"
    $y = "'quoted words'";
    $y =~ s/^'(.*)'$/$1/;  # retira aspas simples,
                           # $y contém "quoted words"
Com o operador s///, as variáveis capturadas $1, $2, etc. são imediatamente disponibilizadas para uso na expressão de substituição. Com o modificador global, s///g pesquisará e substituirá todas ocorrências da regex na string:
    $x = "I batted 4 for 4";
    $x =~ s/4/four/;   # $x contém "I batted four for 4"
    $x = "I batted 4 for 4";
    $x =~ s/4/four/g;  # $x contém "I batted four for four"
O modificador de avaliação s///e envolve um eval{...} ao redor da string de substituição e o resultado avaliado é substituído pela substring combinada. Alguns exemplos:
    # inverter todas as palavras na string
    $x = "the cat in the hat";
    $x =~ s/(\w+)/reverse $1/ge;   # $x contém "eht tac ni eht tah"
    # converte porcentagem para decimal
    $x = "A 39% hit rate";
    $x =~ s!(\d+)%!$1/100!e;       # $x contém "A 0.39 hit rate"
O último exemplo mostra que s/// pode usar outros delimitadores, tais como s!!! e s{}{}, e mesmo s{}//. Se aspas simples são usadas s''', então a regex e a substituição são tratadas como strings de aspas simples.

O operador split

split /regex/, string quebra a string em uma lista de substrings e retorna aquela lista. A regex determina a seqüência de caracteres com que a string é quebrada. Por exemplo, para quebrar uma string em palavras, use
    $x = "Calvin and Hobbes";
    @word = split /\s+/, $x;  # $word[0] = 'Calvin'
                              # $word[1] = 'and'
                              # $word[2] = 'Hobbes'
Para extrair uma vírgula que delimita uma lista de números, use
    $x = "1.618,2.718,   3.142";
    @const = split /,\s*/, $x;  # $const[0] = '1.618'
                                # $const[1] = '2.718'
                                # $const[2] = '3.142'
Se a regex vazia // é usada, a string é quebrada em caracteres individuais. Se a regex tem agrupamentos, então a lista produzida contém também as substrings combinadas dos agrupamentos:
    $x = "/usr/bin";
    @parts = split m!(/)!, $x;  # $parts[0] = ''
                                # $parts[1] = '/'
                                # $parts[2] = 'usr'
                                # $parts[3] = '/'
                                # $parts[4] = 'bin'
Desde que o primeiro caracter de $x combinou com a regex, split acrescenta ao começo da lista um elemento inicial vazio.

voltar para o topo


BUGS

Nenhum.

voltar para o topo


VEJA TAMBÉM

Este é apenas um guia inicial rápido. Para um tutorial mais detalhado sobre regexes, veja the perlretut manpage e para a página de referência veja the perlre manpage.

voltar para o topo


AUTOR E COPYRIGHT

Copyright (c) 2000 Mark Kvale All rights reserved. This document may be distributed under the same terms as Perl itself.

voltar para o topo


AGRADECIMENTOS

The author would like to thank Mark-Jason Dominus, Tom Christiansen, Ilya Zakharevich, Brad Hughes, and Mike Giroux for all their helpful comments.

voltar para o topo


TRADUZINDO

MarcoLima; Thiago Nascimento

voltar para o topo