Utilizando "expr" para "String Matching" através de expressões regulares em shell

Este artigo tem por intuito mostrar mais uma técnica de "String Matching" em shell tirando proveito de RegEx através do comando "expr". Este comando é encontrado na maioria dos sistemas operacionais UNIX, o que facilita o desenvolvimento em plataformas sem ferramentas GNU instaladas. No Linux, o comando faz parte do pacote "coreutils".

[ Hits: 31.529 ]

Por: Alexandre de Abreu em 16/05/2005


Utilizando expressões regulares



Todos sabemos que o domínio do tópico "Expressões Regulares (RegEx)" é de grande valia e utilidade para qualquer programador, principalmente àqueles que utilizam linguagens scripting como Perl, PHP, Shell, Python, Ruby, estas muitas vezes utilizadas na manipulação de Strings.

O expr possui suporte à RegEx, assim como o comando "grep", logo validar expressões torna-se um trabalho viável mesmo sem o "GNU grep/egrep", estes nem sempre estão disponíveis em algumas versões/sabores do UNIX.

A sintaxe para o processamento de uma string ou validação contra um padrão (pattern) utilizando expressões regulares através do comando "expr" pode ser feita de duas maneiras:

  expr     STRING : REGEXP

  expr     match STRING REGEXP

Adotaremos aqui a primeira sintaxe mostrada acima. Para tentarmos entender como funcionam as RegEx juntamente com o comando expr, nada melhor que exemplos. Logo abaixo seguem alguns comandos com pequenos comentários, alguns deles acompanhados do comando equivalente utilizando o "GNU grep":

Cadeias de caracteres ou strings que começam por "D" precedidas ou não de um ou mais espaços ou caracteres de tabulação(TAB):

$ expr " Dicas" : '[[:blank:]]*D'
2

$ expr "Dicas" : '[[:blank:]]*D'
1

$ expr "   Dicas" : '[[:blank:]]*D'
4

Primeiramente deve-se deixar claro que, como na maioria dos casos no mundo UNIX, a string é tratada de modo "Case Sensitive", ou seja "D" é diferente de "d".

O caractere "^", que geralmente determina o início de uma cadeia de caracteres, é implícito, ou seja, o "expr" por si só já entende que o padrão acima descrito, utilizando a RegEx '[[:blank:]]*D', é equivalente ao utilizado através do comando "grep":

$ echo "   Dicas" | grep "^[[:blank:]]*D"
   Dicas

O comando acima seria o equivalente ao último comando "expr" mostrado, veja que ele utiliza o caractere "^" para determinar o início da linha ou da cadeia de caracteres.

Página anterior     Próxima página

Páginas do artigo
   1. Introdução
   2. Utilizando expressões regulares
   3. Como validar expressões
   4. Exemplo prático
Outros artigos deste autor
Nenhum artigo encontrado.
Leitura recomendada

Definição automática de wallpaper em função do horário

Expressões regulares no Bash : parte I

Monitorar servidores e enviar alertas por e-mail e SMS

Operadores de redirecionamento

Recebendo seu IP dinâmico via email

  
Comentários
[1] Comentário enviado por fabio em 16/05/2005 - 23:27h

Belo artigo! Bom, analisando o padrão do exemplo da página 4, aí vai uma expr um pouco mais simples para se extrair o PID do processo:

expr "Apr 26 09:27:01 localhost sshd[2549]: error: Address already in use." : '.*\[\([[:digit:]]\{1,\}\)\]'

O entendimento da mesma fica como dever de casa :P

[]'s,
Fábio

[2] Comentário enviado por inode em 16/05/2005 - 23:34h

Olá Fábio,

O objetivo não é conseguir a informação de maneira mais fácil e sim de maneira mais segura e confiável. Veja que sua regex gera falso-positivos. Um exemplo:

expr "Apr 26 09:27:01 localhost sshd[2549]: error [4567]: Address already in use." : '.*\[\([[:digit:]]\{1,\}\)\]'
4567

:)

[]s

Alexandre de Abreu

[3] Comentário enviado por fabio em 17/05/2005 - 00:26h

Opa,

Mas na linha de log que você mostrou não há exemplo de duas ocorrências de par de chaves []. Uma expressão regular é construída a partir da análise de um padrão e o padrão que segui foi o citado no artigo.

Além do mais, em artigos introdutórios como o seu, devemos sempre priorizar os comandos mais simples para deixar o texto mais didático. Aposto cinco mangos contigo que 90% dos que lerem esse artigo e não forem experts em expressões regulares vão custar ou não vão entender bulúfas da página 4.

Conclusão, era mais fácil concordar que minha regex é uma alternativa resumida à sua :)

[]'s,
Fábio

[4] Comentário enviado por inode em 17/05/2005 - 01:13h

Fábio,

Abra uma sessão: Tópicos Avançaos em Shell com Expressões Regulares, coloque o artigo lá ou ainda, deixe claro que os artigos não podem ser direcionados a usuários que não sejam "experts" como você falou e assim ficamos em paz. :)

Se vamos discutir isso, que seja dito a verdade, a expressão regular para tal tarefa é a descrita no artigo, ele valida uma entrada com o padrão:

^Mes Dia HH:MM:SS Hostname software[PID] Qualquercoisa/Whatever

Escrevi o artigo no intuito de mostrar uma ferramenta e não descrever o tópico RegEx, além disso, não julgo o artigo como introdutório em lugar algum.

Valeu

Alexandre


[5] Comentário enviado por fabio em 17/05/2005 - 02:45h

Mas então, quando buscamos criar uma expressão regular, o objetivo é sempre chegar a mais simples e resumida possível. Analisando sua entrada com o padrão:

^Mes Dia HH:MM:SS Hostname software[PID] Qualquercoisa/Whatever

Podemos concluir que a informação desejada é a única que está entre colchetes. Daí o surgimento de uma expressão que busca somente as informações dentre os próprios colchetes. Não é necessário fazer a expressão "casar" com o resto do padrão se este resto não nos interessa.

Se na aula de história você vai falar sobre o homo-sapiens, não precisa falar sobre o ?homo-herectus? para o professor ou a turma entender o que é homo-sapiens. hehehe

Sua regexp está certa e completa, mas estou, através dos comentários, mostrando que nesse assunto temos diversas formas para chegarmos a um resultado final. Você respondeu como se fosse o dono da verdade, morfando o padrão da linha para uma situação imaginária só pra dizer que minha sugestão estava incorreta, mas não é por aí. Notei que sua personalidade era assim nos e-mails que me enviou antes e depois do artigo ser publicado... bom, mas isso é assunto nosso, deixa pra lá!


[]'s,
Fábio

[6] Comentário enviado por inode em 17/05/2005 - 09:59h

Cara, que comédia, eu tento mostrar algo interessante no artigo sobre expr ai vem você criticar uma simples RegEx. Que infelicidade a minha! :)

Não sou dono da verdade Fábio, mas, se é para mostrar algo, que seja mostrado da forma correta. Você tem muito que aprender ainda sobre RegEx, um dia saberá que um falso-positivo acaba com seu sistema e que o importante é segurança e confiabilidade, e não fazer a RegEx mais simples possível. Iss cabe um novo artigo, não?

Para acabar com a discussão: sua RegEx funciona! Ela retorna o último número entre colchetes, é isso que quer ler?

Bom dia! ;)

[7] Comentário enviado por lyma em 17/05/2005 - 11:48h

Gostaria de interromper esta produtiva discussão para parabenizar sobre o ótimo artigo.

Um abraço aos dois! :)

[8] Comentário enviado por inode em 17/05/2005 - 12:55h

Valeu lyma, qualquer dúvida manda ai. :)

[9] Comentário enviado por agk em 02/06/2005 - 14:51h

Bastante interessante o artigo, mas para entendê-lo melhor teria que me aprofundar um pouco mais em Shell Script como diz no final do artigo.

[10] Comentário enviado por agressiveinlinux em 18/08/2010 - 15:16h

Pessoal não sei se minha dúvida é sobre o assunto, mas lá vai, estou precisando saber qual comando uso para encontrar caracteres ascii em um texto, já tentei usar o find mais nada, o grep dá algum suporte ou vocês sabem de outro comando para fazer isso.

Obrigado!!


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts