Acesso direto ao conteúdo
Logotipo Dicas-L, por Ricardo Burile

Busca

Visite também: Segurança Linux ·  UnderLinux ·  VivaOLinux ·  LinuxSecurity ·  NoticiasLinux ·  BR-Linux ·  SoftwareLivre.org ·  [mais]   
 

Você está aqui: Home  → Arquivo Dicas-L

 

Curso de Inglês Online

Assine a Lista Dicas-L

Receba diariamente por email as dicas
de informática publicadas neste site
Para se descadastrar, clique aqui.

Expr - Processamento de Strings utilizando Expressões Regulares ou RegEx

Colaboração: Alexandre de Abreu

Data de Publicação: 27 de Maio de 2005

O comando expr é muito conhecido pelos programadores shell(bash, ksh, sh, etc.), mas, a sua utilização, na maioria das vezes, restringe-se ao comando abaixo:

  contador=`expr $contador + 1`

Este comando irá incrementar o valor da variável contador em 1. Outras formas de alcançar o mesmo objetivo em Bash seriam:

  let contador++
  contador=$((contador+1))
  contador=$(bc <<< "$contador + 1")

É verdade que existem várias outras maneiras de fazer, mas o foco deste documento é apresentar as funcionalidades do comando expr, um poderoso processador de expressões.

Esse comando pode ser utilizado para processar expresões matemáticas através de operadores lógicos como |, >, >=, &, que representam o OU, E, MAIOR QUE, etc., assim como também pode utilizar operadores aritméticos como visto no exemplo acima com o operador de adição ou +. Outras possibilidades são % ou módulo, * ou multiplicação.

Abaixo veremos exemplos de expressões aritméticas utilizando alguns operadores assim como os parênteses para agrupar e definir a ordem de execução dos comandos:

  $ expr \( 30 + 2 \) \* \( 13 % 2 \) - \( 2 \* \( 20 - 8 \) \)
  8
  $ expr \( 30 + 2 \) \* \( 13 % 2 \) - \( 2 \* \( 20 - 8 \) \) / 2
  20
  $ expr \( \( 30 + 2 \) \* \( 13 % 2 \) - \( 2 \* \( 20 - 8 \) \) \) / 2
  4
  

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

O expr possui suporte à RegEx, assim como o comando grep. Validar expressões torna-se um trabalho viável mesmo sem o GNU grep/egrep, ique 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 utilizar exemplos. A seguir incluimos alguns comandos com pequenos comentáros, alguns deles acompanhandos do comando equivalente utilizando o GNU grep:

  1. 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 caracter ^, 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.

    Voltando ao comando: expr " Dicas" : '[[:blank:]]*D'

    Verificamos que a saída padrão é igual a 4, pois, de acordo com a String que foi testada contra o padrão em RegEx acima existem 4 caracteres que estão de acordo com a cadeia " Dicas": 3 espaços e o caracter D.

    O expr imprime na saída padrão o número de caracteres que estão de acordo com o padrão testado, no último caso, 4. Veremos logo abaixo como imprimir os caracteres que estão de acordo com o padrão especificado na linha de comando, o que é bem mais interessante e útil.

    Vejam que a String " Dicas" está entre aspas duplas e não entre aspas simples. É interessante sempre adotar este procedimento, pois, ao utilizar variáveis, o valor da variável é utilizado durante a expressão:

      $ STR="   Dicas"
      $ expr "$STR" : '[[:blank:]]*D'
      4
      
    
  2. Como validar uma expressão?

    Qual seria o comando expr para validar uma String que pode ser resultado de uma entrada de usuário utilizando o read, uma linha de um arquivo ou saída padrão de um comando? Utilizando grep, teremos:

      $ STR="localhost.localdomain"
      $ echo "$STR" | grep -q "localhost" && echo OK
      OK
      
      if grep -q "localhost" /etc/hosts; then
       echo "Existe"
      else
       echo "Não existe"
      fi
      
    

    Estes exemplos são bem simples, o parâmetro -q do comando grep suprime a saída padrão. O Bash ainda possibilita a utiliação da forma abaixo para Pattern Matching:

      $ STR="localhost.localdomain"
      $ [[ $STR = l* ]] && echo OK
      OK
      
    
    Mas, ainda assim não será suficiente para alguns casos, como veremos a seguir. Um exemplo mais interessante seria a validação de um nome de diretório/arquivo ou uma String em relação ao padrão resultante do comando date abaixo:

      $ date '+%d%m%y-%T'
      260405-11:52:52
      
    
    O expr pode ser empregado nesta situação. Abaixo veremos que a representação [[:digit:]] equivale aos números de 0 a 9 ou [0-9]. Vejamos como seria o comando correto para validação:

      $ STR=``date '+%d%m%y-%T'``
      $ expr "$STR" : '[[:digit:]]\{6\}-[[:digit:]]\{2\}:[[:digit:]]\{2\}:[[:digit:]]\{2\}'
      15
      $ echo $?
      0
      
    
    Como vimos, o comando expr acima retorna 0, ou seja, quando há um matching ele retorna true ou verdadeiro: variável $? igual a 0. O valor de retorno pode ser armazenado em uma variável e posteriormente verificado através dos comandos abaixo:

      STR="Dicas-Linux eh legal"
      
      expr "$STR" : '.*Linux.*' > /dev/null
      
      if [ $? -eq 0 ]; then
       echo "Encontrado"
      else
       echo "Nada encontrado"
      fi
      
    
    O padrão acima corresponde a qualquer cadeia que contenha a palavra Linux. O caractere . equivale a qualquer caractere. O retorno será verdadeiro, logo, será mostrado na tela a palavra Encontrado.

    Como retornar a cadeia que está de acordo com o padrão especificado? Resposta: Utilizando parênteses. Vamos a um exemplo simples, mostrando o comando utilizado no começo deste documento:

      $ expr "   Dicas" : '\([[:blank:]]*D\)'
        D
      
    
    Este comando retorna os caracteres da String que estão de acordo com o padrão especificado através da RegEx e demarcados pelos parênteses. Note que os parênteses devem ser escapados com contra-barras para que não sejam entendidos como um caractere literal ( ou ).

  3. Como retirar da String abaixo o número de identificação do processo(PID)?

      # tail -1 /var/log/secure
      Apr 26 09:27:01 localhost sshd[2549]: error: Address already in use.
                                    
      
    
    Uma RegEx válida para esta situação seria:

      '[[:upper:]][[:alpha:]]\{2\} [[:digit:]]\{2\} [:[:digit:]]\{8\} [[:alnum:]]\{1,\} [[:alnum:]]\{1,\}\[[[:digit:]]\{1,\}\]: '
      
    
    Note que é possível especificar o número de ocorrências para cada representação(dígitos, alfa-numéricos, etc.) indicando este número entre chaves com contra-barras: \{2\}, \{1,\}. Este último quer dizer um ou mais.

    Ao executar o comando abaixo vimos que ele retorna o número de caracteres:

      $ expr "Apr 26 09:27:01 localhost sshd[2549]: error: Address already in use." : '[[:upper:]][[:alpha:]]\{2\} [[:digit:]]\{2\} [:[:digit:]]\{8\} [[:alnum:]]\{1,\} [[:alnum:]]\{1,\}\[[[:digit:]]\{1,\}\]: '
      38
      
    
    Mas, se adicionarmos os parênteses com contra-barras na sub-cadeia que desejamos obter (PID), teremos:

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

Este documento teve por finalidade mostrar uma das funcionalidades do comando expr com relação a processamento de Strings. Esta ferramenta faz parte do pacote coreutils ou fileutils dependendo da distribuição Linux. Faz parte também da maioria dos sistemas operacionais UNIX (testei em AIX, HP-UX e SunOS/Solaris).

Lógico que, para tirar o máximo desta funcionalidade é necessário um bom conhecimento sobre Expressões Regulares. Para quem ainda não tem tanto conhecimento neste tópico, a melhor referência é o livro Expressões Regulares - Uma Abordagem Divertida, de autoria de Aurélio Marinho Jargas.

Veja a relação completa dos artigos de Alexandre de Abreu

Formato PDF
Newsfeed RSS
Formato para impressão
PDF RSS Imprimir

Referências Adicionais

Referências adicionais sobre os assuntos abordados neste site podem ser encontradas em nossa Bibliografia.

Avalie esta dica

  • Currently 3.00/5
  • 1
  • 2
  • 3
  • 4
  • 5

Avaliação: 3.0 /5 (1127 votos)

Opinião dos Leitores

Seja o primeiro a comentar este artigo
*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
Lan University

Submarino.com.br

Encontre imóveis, apartamentos e casas a venda no Imobilien
Saiba mais

 

 

Procure pela casa ou apartamento ideal à venda ou para aluguel na busca inteligente do Imohoo
Buscar imóveis