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".
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.
[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:
[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 :)
[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.
[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á!
[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?
[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.