você está aqui: Home  → Arquivo de Mensagens

Para que servem as expressões regulares - alguns exemplos

Colaboração: Julio Cezar Neves

Data de Publicação: 25 de julho de 2018

Partindo de um determinado padrão de dado, as Expressões Regulares podem ser utilizadas para:

1. Pesquisar um arquivo por todas as ocorrências que casam com esse padrão. Para fazer isso o ideal é usar os comandos grep, awk ou sed.

A Expressão Regular para definir telefones celulares no formato (NN)NNNNN-NNNN com ou sem parênteses é:

'^\(?[0-9]{2}\)?[0-9]{5}-?[0-9]{4}$'
Onde Significa
^ Início do texto
\(? e \)?
Parenteses do DDD escapados (\) por serem metacaracteres e opcionais (?)
[9-0]{N} Qualquer algarismo que se repete N vezes
$ Fim do texto

Para testar, coloque o número do seu celular entre as aspas que estão no final do grep a seguir:

if  grep -Eq '^\(?[0-9]{2}\)?[0-9]{5}-?[0-9]{4}$' <<< ""
then echo Casou
else echo Solterou
fi

A Expressão Regular para definir telefones fixo no formato (NN)NNNN-NNNN com ou sem parênteses é quase igual a anterior:

'^\(?[0-9]{2}\)?[0-9]{4}-?[0-9]{4}$'

Teste a Expressão Regular com um telefone fixo aqui:

if  grep -Eq '^\(?[0-9]{2}\)?[0-9]{4}-?[0-9]{4}$' <<< ""
then echo Casou
else echo Solterou
fi

Então para casar com fixo e celular, basta repetir a Expressão Regular do fixo, inserindo mais um algarismo opcional, ficando:

'^\(?[0-9]{2}\)?[0-9]{4}[0-9]?-?[0-9]{4}$'

E para testá-la use:

if grep -Eq '^\(?[0-9]{2}\)?[0-9]{4}[0-9]?-?[0-9]{4}$' <<< ""
then echo Casou
else echo Solterou
fi

2. Alterar num arquivo por todas as ocorrências que casam com um padrão. Para fazer isso o ideal é usar o comando sed ou awk.

Num arquivo que contem datas no padrão inglês (MM/DD/AAAA), vamos invertê-las para o nosso padrão (DD/MM/AAAA).

Para isso vamos usar o sed com seu comando s (substitute), que troca todos os textos que casam com a Expressão Regular que está na primeira parte do comando, pelo texto definido na segunda parte. Veja o comando:

sed -r 's|([0-9]{2})/([0-9]{2})/([0-9]{4})|\2/\1/\3|' arquivo
Onde Significa
| Delimitador das duas partes do comando substitute (s)
[0-9]{N} Dia, mês e ano
\1,\2 e \3 Retrovisores

É muito bacana notarmos que o mês, o dia e o ano receberam um par de parênteses envolvendo cada um. Esses parênteses não têm o menor efeito na Expressão Regular, mas eles guardam o texto casado por cada um deles, que podem ser recuperados pelos retrovisores, que são numerados pela ordem da sua ocorrência na Expressão Regular, como fizemos, porém trocando o segundo pelo primeiro,

3. Testar se um dado é válido. Para fazer isso, o ideal é usar o novo comando test ou o grep.

No exemplo anterior, não interessava saber se as datas eram corretas ou não, pois já estavam armazenadas em um arquivo e por isso partimos do pressuposto que estavam certas. Agora temos um outro problema estamos recebendo datas de um meio externo e antes de gravá-las temos de verificar sua correção:

if [[ $Data =~ ^(0[1-9]|[12][0-9]|3[01])/(0[1-9]|1[012])/[0-9]{4}$ ]]
then echo Data OK
else echo Data NOK
fi
Onde Significa
(0[1-9]|[12][0-9]|3[01])
Dia de 01 a 09 ou (|) de 10 a 19 ou 30 a 31
(0[1-9]|1[12]) Mês de 01 a 09 ou 10 a 12
[0-9]{4} Ano com 4 algarismos

Agora coloque uma data válida e uma invalida na variável Data e teste. Após testar uma data válida, execute:

echo ${BASH_REMATCH[@]}

Isso é um vetor do sistema que contém a saída do último comando test (que é o [[...]]). Ele tem no seu índice zero (${BASH_REMATCH[0]}) tudo que casou e nos índices seguintes o que seriam os retrovisores, isto é, em ${BASH_REMATCH[1]} tem o dia e em ${BASH_REMATCH[2]} tem o mês. Quando listamos ${BASH_REMATCH[@]} mostramos todos os índices do vetor.

Além disso que vimos, é muito fácil manipular tudo que conhecemos a regra (o que venho chamando de padrão), como endereço de e-mail, site, CEP, endereço IP, endereço mac, variáveis do sistema (começam por cifrão e só podem ter letras maiúsculas e/ou alguns caracteres especiais após).

Costumo dizer - e tenham certeza que isso é uma verdade - que você só descobre a imensa quantidade de usos e de economia de código propiciada pelas Expressões Regulares depois que as conhece e sabe usá-las

Para finalizar, um cartoon sobre expressões regulares, de autoria de Randall Munroe, criador da série Xkcd:



Veja a relação completa dos artigos de Julio Cezar Neves

 

 

Opinião dos Leitores

julio neves
03 Ago 2018, 11:59
Fala João Paulo,
100% correta a sua observação... Mais uma bobeada minha, mas as ERs muitas vezes nos enganam pq as fazemos com uma ideia pré concebida estilo "cada um no seu quadrado" e isso não nos permite ver o todos.
Uma vez, botei no meu site uma ER para critica de horário, que era assim:

[[ $Hora =~ ([01][0-9]|2[0-3]):[0-5][0-9] ]] || echo data inválida

Isso ficou assim anos e ninguém notou pq todos pensam em hora e minuto com 2 algarismos cada, mas um dia me chamaram a atenção que isso casaria com 123:456
pq casa com o pedaço 23:45. Faltou colocar as bordas.

Algum tempo depois, brincando com phyton fui consultar o site do Guido van Rossum (criador da linguagem) e vi que ele tinha dado a mesma bobeada que dei na crítica de data...

Acho que o mais difícil das ERs é pensar fora do quadrado.

Obrigado pela correção.
Joao Paulo
02 Ago 2018, 22:12
Mestre Júlio,

nos telefones:

as expressões como (8499937-7777 e 84)99937-7775 também casariam. Poderia ser então:

grep -Eq '^(\([0-9]{2}\)|[0-9]{2})[0-9]{5}-?[\d]{4}$'

Abraço
julio neves
25 Jul 2018, 14:35
Uma grande bobeada de minha parte... Antigamente só haviam 10 meses e por isso temos:
Sete-mbro mês 9
Oito-ubro mês 10
Nove-mbro mês 11
Dez-embro mês 12
Essa minha ER é o começo do resgate do calendário pré gregoriano... ;)

Bobeada séria... Extingui o mês 10! Repare que, lendo a ER, montei a tabelinha para explicá-la e até na tabela omiti o mês 10.

Valeu André vou pedir ao Rubens para corrigir,
suShellso ;)
André Geraldo Vieira
25 Jul 2018, 14:14
Mestre Júlio,

Longe de mim querer corrigir um Grande Mestre das Expressões Regulares.
Mas creio que a expressão regular, que foi utilizada no exemplo, não está correta.
A expressões correta seria:
^(0[1-9]|[12][0-9]|3[01])/(0[1-9]|1[012])/[0-9]{4}$ ]]
e não:
^(0[1-9]|[12][0-9]|3[01])/(0[1-9]|1[12])/[0-9]{4}$ ]]

Faltou um "0" (zero) na validação do mês.

Atenciosamente,
André Geraldo Vieira
*Nome:
Email:
Me notifique sobre novos comentários nessa página
Oculte meu email
*Texto:
 
  Para publicar seu comentário, digite o código contido na imagem acima
 


Powered by Scriptsmill Comments Script