Awk - Uma poderosa ferramenta de análise

Publicado por Leonardo Berbert Gomes em 01/07/2009

[ Hits: 117.946 ]

Blog: https://www.linkedin.com/in/leoberbert

 


Awk - Uma poderosa ferramenta de análise



A linguagem awk é muito conhecida por sua eficácia em criar filtros de conteúdos de arquivos. Nessa dica vou ensinar alguns truques que facilitarão a vida de todos.

Vamos tomar como base o arquivo leo.txt, que tem o seguinte conteúdo:

188 :2106102121 192.168.0.89
267 :2206211021 192.168.0.88
438 :2306211021 192.168.0.87

1. Preciso mostrar na tela a primeira coluna do arquivo:

cat leo.txt | awk '{print $1}'
188
267
438

Entendendo:
  • print $1 -> Exibe a primeira coluna;
  • print $2 -> Exibe a segunda coluna e assim por diante;
  • print $NF ->Exibe a última coluna.

2. Em seguida me foi solicitado que contasse as linhas do resultado acima, para isso podemos utilizar outro comando após o resultado:

cat leo.txt | '{print $1}' | wc -l

3. Suponha que eu necessite vasculhar esse arquivo e mostrar apenas os campo com dia e mês, repare que na frente do dia existe um ":" que nos atrapalharia um pouco nessa busca. Vou usar o comando cat para mostrar que o awk pode ser combinado com os comandos do shell:

  • cat leo.txt | awk -F ":" '{print substr($2,1,4)}'
  • 2106
  • 2206 2306

    Entendendo:
    • awk -F ":" -> Ignora o caractere ":" da segunda coluna;
    • {print substr($2,1,4)}' -> Exibe a segunda coluna do primeiro ao quarto caractere.

    4. Agora eu gostaria que, após mostrar esse resultado, ele fizesse um filtro por uma data específica, vou tomar como seleção "2106":

    cat leo.txt | awk -F ":" '{print substr($2,1,4)}' | grep 2106
    2106

    5. Vamos dificultar um pouco as coisas agora. Eu agora tenho um outro arquivo (leo2.txt) com o seguinte conteúdo:

    183201
    183202
    183203
    183204
    183205
    183206
    183207
    183208
    183209

    6. Me foi solicitado que fizesse um filtro para descobrir todos os campos de 18:32:02 até 18:32:08. Observe que aqui estaremos trabalhando com um intervalo. Então ficaria da seguinte forma:

    cat leo2.txt | awk '{if (($1) >= "183202" && ($1) <= "183208") print}'
    183202
    183203
    183204
    183205
    183206
    183207
    183208

    Obs.: Neste último exemplo temos uma condição que deve ser atendida, se verdadeira, exibe o resultado encontrado.

    Pessoal, espero ter ajudado. Em breve darei continuidade à dica com mais truques de Awk.

    Outras dicas deste autor

    Grok, um excelente plugin para o logstash

    Compilando a última versão do VIM em Debian, Mint, Ubuntu e derivados

    Compilando a última versão do Vim no Fedora 33

    Backup dos arquivos em determinado diretório

    Mantendo um alto padrão de segurança

    Leitura recomendada

    Utilizar um Link Simbólico

    Exemplo para o comando Xargs

    Descompactando arquivos ZIP divididos em partes

    Extraindo arquivos de um .rpm sem instalá-lo

    Monitorando um comando com strace

      

    Comentários
    [1] Comentário enviado por removido em 10/07/2009 - 11:26h

    Muito fera este awk apesar de ser desconhecido por muitos linuxers

    [2] Comentário enviado por diegrocha em 27/02/2010 - 17:57h

    Gostei da dica. muito boa mesmo!

    abçs

    [3] Comentário enviado por removido em 25/10/2010 - 16:22h

    Otima dica.

    [4] Comentário enviado por chimico em 31/03/2012 - 11:54h

    Muito boa dica
    Favoritado!

    [5] Comentário enviado por cordobel em 24/07/2012 - 09:54h

    Bom dia pessoal. É muito bom mesmo o awk. E aproveitando que este post me ajudou no trabalho agora mesmo no momento em que escrevo este comentário, vou resumir a situação para poder dar um esclarecimento a mais sobre o funcionamento do awk.

    Veja o seguinte trexo da saída do comando dir do windows:

    01/18/2011 01:47 PM <DIR> server_128
    01/18/2011 02:26 PM <DIR> server_131
    01/18/2011 02:53 PM <DIR> server_133
    01/18/2011 03:17 PM <DIR> server_135
    01/18/2011 04:17 PM <DIR> server_136
    01/19/2011 08:16 AM <DIR> server_139
    01/19/2011 08:23 AM <DIR> server_140

    Eu precisava fazer um diff de dois diretórios, (origem e backup) por isso salvei a saída do dir de cada um.
    Mas como as datas em item de cada diretório também são diferentes, o diff iria acusar que todas as linhas são diferentes, o que não ia me ajudar em nada.
    Logo eu deveria dar um jeito de salvar apenas o conteúdo da última coluna.

    A princípio eu achava que o awk considerava as colunas assim como são consideradas as colunas por meio de um editor de texto, ou seja, cada caractere da linha é uma coluna.
    E se observer o exemplo que dei, cada linha tem muitos caracteres em branco, que são considerados uma coluna cada um, no caso de um editor de texto.

    Mas ao testar o awk notei que ele considera coluna, um conjunto de caracteres não brancos ou palavra, logo o comando:

    cat saida_dir_c_server.txt | awk '{print $5}'

    já resolveu o meu problema, imprimindo na tela a penas o último conjunto de caracteres ou última palavra de cada linha, da seguinte maneira:

    server_128
    server_131
    server_133
    server_135
    server_136
    server_139
    server_140

    Resumindo, não importa o números de caracteres em branco separando as colunas, o awk considera as palavras.

    [6] Comentário enviado por cordobel em 24/07/2012 - 09:59h

    Poxa vida, que pena. Ao salvar o comentário o site desconsiderou o excesso de caracteres em branco que aparecem na saída do comando dir do windows. Mas para que tenham uma noção o maior excesso fica entre a coluna do <DIR> e do server_1**

    [7] Comentário enviado por ram0nes em 27/08/2014 - 14:46h

    parabéns Leonardo vlw gostei gostaria tbm de um exemplo.

    supor que eu tenha uma lista contendo diversos ips assim 200.0.11.87(201-0-11-87.dsl.telesp.net.br):21 :220 TelNet Server (Debian) [::ffff:201.0.11.87] como eu faria para deixar somente o ip ?
    200.0.11.87

    grato vlws...

    [8] Comentário enviado por leoberbert em 27/08/2014 - 18:27h

    ram0nes,

    Em primeiro lugar vc precisa identificar o separador, nesse caso usei o parenteses "(" veja abaixo:

    cat lista

    200.0.11.87(201-0-11-87.dsl.telesp.net.br):21 :220 TelNet Server (Debian) [::ffff:201.0.11.87]

    Mostrando apenas a primeira coluna:

    cat lista | awk -F "(" '{print $1}'

    200.0.11.87

    []'s leoberbert

    [9] Comentário enviado por leoberbert em 27/08/2014 - 18:34h

    ram0nes,

    Também poderia utilizar o perl para isso:

    cat lista | perl -ne '/^(\d*).(\d*).(\d*).(\d*)/;print "$1.$2.$3.$4\n" '
    200.0.11.87

    []'s leoberbert

    [10] Comentário enviado por antonioamazonas em 10/06/2015 - 01:25h

    Olá Leonardo, olá a todos.
    Sou Novo no multiverso LINUX e novo também no forum, comecei a usar o Ubuntu modo texto.
    estou com alguns exercícios da faculdade que utiliza o "awk"

    Ex:
    tenho uma lista que se chama "nomes.dat" (a extensão é somente um parâmetro organizacional) com nomes e Ids de usuários ex:

    100 Suzana Alves
    101 Maria joaquina
    102 Castro Alves
    103 Suzana Vieira

    Tenho outro arquivo chamado "telefones.dat" com as seguintes informações:

    1000 100 1111-0000
    1001 100 1111-1111
    1002 100 2222-2222
    1003 101 3333-3333
    E assim sucessivamente...

    O que o professor pede é que seja feito um codigo que receba como parametro um nome e imprima as linhas do arquivo nomes.dat que o contenham
    2 outro que faça a mesma coisa mas que só imprima os nomes
    3 Que receba como primeiro parametro um numero da primeira coluna e imprima as linhas do arquivo telefones,dat que a segunda coluna contenham esse código
    e tem outras variações mas que se eu conseguir fazer um ou dois, creio que consiga desenvolver os outros.

    estudando o comando "awk" percebi que se eu digitasse :

    awk -F " "'/jorge/ {print $2,$3;}' nomes.dat

    Ele me retornava o nome "jorge amado" do arquivo nomes.dat

    comecei a fazer o código assim:


    #!/bin/sh

    read -p " Digite o nome do contato e pressione <ENTER> " CONTATO
    echo " Buscando dados de $CONTATO, por favor aguarde..."
    slep 2
    clear

    BUSCAR=`awk -F " "'$CONTATO {print $2,$3;}' nomes.dat`

    mas ao fazer isso o codigo retorna erros .

    desejo aber com faço para que o comando awk leia o conteúdo armazenado na variável CONTATO e busque no arquivo nomes.dat e me retorne a linha correspondente ao nome e sobrenome do contato?
    Desculpem caso tenha postado em uma área indevida.
    Agradeço a todos!


    [11] Comentário enviado por edulinuxx em 28/08/2015 - 14:24h


    Show!

    [12] Comentário enviado por calumby em 04/11/2015 - 10:14h

    olá tenho um duvida , de como filtra dados pois tenho essas informações

    0.044061
    0.277940
    1.044061
    1.277940
    2.044061
    2.277940
    3.044061
    3.277940
    4.044061
    4.277940
    5.044061
    5.277940
    6.044061
    6.277940
    7.044061
    7.277940
    8.044061
    8.277940
    9.044061
    9.277940
    10.044061
    10.277940
    11.044061
    11.277940
    12.044061
    12.277940
    13.044061
    13.277940
    14.044061
    14.277940
    15.044061
    15.277940
    16.044061
    16.277940
    17.044061
    17.277940
    18.044061
    18.277940
    19.044061
    19.277940
    20.044061
    20.277940
    21.044061
    21.277940
    22.044061
    22.277940
    23.044061
    23.277940
    24.044061
    24.277940
    25.044061
    25.277940
    26.044061
    26.277940
    27.044061
    27.277940
    28.044061
    28.277940

    isso e um arquivo gerado pelo ns2 preciso filtrar , tirar os números ante do ponto por exemplo 28.277940 caso teria de ficar assim 277940 so esse resultado tem que ficar, ja procurei varios comandos ainda não encontrei, teho que tirar todos de uma so vez!

    [13] Comentário enviado por leoberbert em 04/11/2015 - 11:46h

    calumby,

    Sua dúvida é simples, basta você fazer assim:

    head teste | awk -F "." '{print $2}'

    044061
    277940
    044061
    277940
    044061
    277940
    044061
    277940
    044061
    277940

    tail teste | awk -F "." '{print $2}'
    044061
    277940
    044061
    277940
    044061
    277940
    044061
    277940
    044061
    277940

    Quando usa o -F em seguinda você define o delimitador e sem seguida você escolhe qual coluna exibir.

    Espero ter ajudado.

    []'s leoberbert

    [14] Comentário enviado por thiagosabo em 11/01/2017 - 06:53h

    Ai sim Leonardo Berbert Gomes, valew pela iniciativa!!

    Apenas uma correção... o ":" não ignora, ele considera que o : seja o separador de campo.

    Parabéns!!!



    Contribuir com comentário




    Patrocínio

    Site hospedado pelo provedor RedeHost.
    Linux banner

    Destaques

    Artigos

    Dicas

    Tópicos

    Top 10 do mês

    Scripts