Interessante uso para o awk em um script

Uma coisa legal de dar uma nova roupagem a um antigo projeto é ganhar um gás para escrever sobre assuntos que achávamos que já não tínhamos mais tanto a oferecer.

E vou lhes dizer que é muito legal ganhar esta gás e poder voltar a postar sobre coisas que só nós que somos nerds e apaixonados com TI sabemos valorizar.

E uma destas coisas é o famoso awk.  O awk é uma ferramenta que está em todos os sistemas operacionais baseados em Unix no planeta e é praticamente uma linguagem de programação, sendo possível a partir dela gerar coisa para caramba. Em geral, a maioria das pessoas utiliza o parser que ele tem para filtragem de strings ( posso dizer hoje que 80% do meu uso do awk  é para este tipo de aplicação ) mas ele vai bem além.

Lendo hoje meus feeds no meu kindle dei de cara com uma aplicação bem legal do awk. Na realidade o script abaixo pega o número e cria uma dupla com o múltiplo mais próximo de 10 em números aleatoriamente gerados.

[brsysb]
while true ; do echo $[ 1 + $[ RANDOM % 100 ]] ; done | head -100 | awk '{ bucket = int(($1 + 5) / 10) * 10 ; arr[bucket]++} END { for (i in arr) {print i, arr[i] }}' | sort -k2n,2 -k1n,1

[/brsysb]

Infelizmente muita gente não curte esta idéia de uma linha ( que normalmente é como criamos alguns scripts para resolver problemas quando temos somente uma console disponível ) e gosta de visualizar o script identado e mais claro.

Para estes segue o script acima mais acabadinho e fácil de ser visualizado.

[brsysb]


#!/bin/bash

while true ; do
  echo $[ 1 + $[ RANDOM % 100 ]]
done | head -100 | \
  awk '
      {
        bucket = int(($1 + 5) / 10) * 10 ;
        arr[bucket]++
      }
      END {
        for (i in arr) {
          print i, arr[i]
        }
      }
' | sort -k2n,2 -k1n,1

[/brsysb]

A saída vai ser mais ou menos igual esta aqui.

[brsysb]

$ sh algo.sh 
0 2
50 7
10 8
60 8
80 8
20 9
100 9
40 11
70 11
30 12
90 15

[/brsysb]

Uma outra coisa interessante que pouca gente sabe é que o awk pode criar funções. Sim, você pode criar funções em awk que podem ser utilizadas em outros scripts.

É algo que eu descobri muito tempo depois de conhecer o awk, mas agora o mesmo script acima em função que pode ser utilizada em outros programas ( uma das boas coisas da programação, funções que podem ser reaproveitadas ).

Lembrando que o awk lê estas funções e é só usar a flag -v para utilizar .

[brsysb]

#!/bin/bash

# Bucketize stdin to nearest multiple of argv[1], or 10 if no args given.
# "nearest" means 0..4.999 -> 0, 5..14.999 -> 10, etc.

# Usage:
# while true ; do echo $[ 1 + $[ RANDOM % 100 ]]; done | head -99 | bucket.sh 8

awk -v multiple="${1:-10}" '

function bucketize(a) {
  # Round to the nearest multiple of "multiple"
  #  (nearest... i.e. may round up or down)
  return int((a + (multiple/2)) / multiple) * multiple;
}

# All lines get bucketized.
{ arr[bucketize($1)]++ }

# When done, output the array.
END {
  for (i in arr) {
    print i, arr[i]
  }
}
' | sort -k2n,2 -k1n,1

[/brsysb]
Como o autor do script hoje em dia gosto mais de usar python para estes fins mas o awk realmente se mostrou bem interessante neste caso específico, nem que seja somente para conhecer mais alguma utilidade para o awk 🙂