![]()
A linguagem AWK é uma linguagem para processamento de texto criada para as primeiras versões do Unix. Você pode pensar nela como o avô do RegEx, já que você conseguia criar scripts simples para pesquisa de texto nas linhas dos arquivos que você queria e aí filtrá-las.
A primeira versão dessa linguagem surgiu em 1977 como uma linguagem de script para processamento de textos, ajudando a aumentar o poder dos scripts shell e oferecer novas funcionalidades, características que fizeram o AWK influenciar diversas outras linguagens, como Perl, as novas versões do Shell e Lua.
A linguagem ainda teve atualizações a partir dos anos 80, possibilitando a incorporação do RegEx dentro dos scripts AWK originais.
Com o fim do Unix e construção do GNU/Linux, BSD e outras variações, o AWK original ficou no passado. Porém, principalmente para manter a retrocompatibilidade dos scripts dos usuários do Unix, surgiram diversos interpretadores do AWK. Os mais populares são:
- BWK: é o interpretador mais antigo depois do fim do Unix, tendo envolvimento direto dos criadores originais do AWK, principalmente de Brian Kernighan. Essa versão é usada no FreeBSD, OpenBSD, NetBSD e Mac OS X;
- GAWK: o GNU AWK é o interpretador mais popular hoje, vindo por padrão na maioria das distros Linux e estando disponível também nos repositórios de praticamente todas. Possui usos populares ainda hoje na comunidade, podendo encontrar certos padrões de texto a partir de funções complexas e recebeu atualizações recentes para garantir recursos para operar em redes TCP/IP;
- TAWK: o Thompson AWK é um compilador AWK para DOS, Solaris, OS/2 e Windows. Anteriormente vendido pela Thompson Automation Software, hoje você pode obter ele gratuitamente no site oficial. Apesar de dizer oferecer uma versão para Windows, só possui compatibilidade oficial até o Windows XP, então podem ocorrer bugs em versões posteriores do software da Microsoft;
- AWKA: é um compilador AWK que converte o código em linguagem C e depois o compila, fazendo com que scripts longos sejam interpretados mais rapidamente do que seriam na versão original. O desempenho dos scripts compilados é muito superior se comparado à outras linguagens, e ainda é compatível com o GAWK 3.1.0, possuindo funções nativas para interfaces de rede TCP/IP e outros afins. Você pode baixar no site oficial;
Hello World
Há duas formas de se executar AWK. Uma delas é colocando o comando inline, todo em uma mesma linha, e executá-lo diretamente pelo terminal. A segunda é inserindo o comando inteiro dentro de um arquivo e executando esse arquivo
Direto no terminal
Na primeira vez você pode rodar direto no terminal. Rode o seguinte comando:
awk 'BEGIN{print "Hello World!"}'
Isso vai imprimir Hello World no terminal. Simples, não?
Em um arquivo
BEGIN {
print "Hello World!";
}
Você pode rodar de 2 formas. Na primeira você deve rodar o arquivo com o seguinte comando:
awk -f hello.awk
E pronto, você vai ter Hello World escrito na tela.
Na segunda forma (e mais comum), você adiciona, antes do código, uma hashbang, com o seguinte código:
#!/bin/gawk -f
Isso indicará para o shell qual o interpretador que será usado para rodar o script. Salve o arquivo e rode o seguinte comando:
chmod +x hello.awk
Isso adiciona permissão de execução ao arquivo hello.awk. Agora é só executar:
./hello.awk
E pronto, você terá Hello World escrito na tela.
Uso prático - Listados apenas dados específicos
Vamos trabalhar com o arquivo gender_submission.csv de um dataset do Titanic da Kaggle (disponível aqui). Comecemos imprimindo todas as linhas do arquivo:
cat gender_submission.csv | awk '{print $0;}'
Para esse arquivo você vai precisar alterar o divisor padrão dos items. O padrão do AWK é um espaço, mas o nosso arquivo usa o padrão do CSV, que é uma vírgula. Como mudar isso? Simples, vamos usar o bloco BEGIN. O bloco BEGIN é executado uma única vez no código, antes de todo o resto, enquanto o seguinte é executado uma vez por linha. Então vamos alterar a variável FS, que define o separador dos parâmetros da linha, logo antes de executar o resto do código:
cat gender_submission.csv | awk 'BEGIN{FS=",";} {print $0;}'
Quer saber se deu certo? Que tal colocar duas setas entre um campo e outro?
cat gender_submission.csv | gawk 'BEGIN{FS=",";}{print $1 " → → " $2}'
O nosso objetivo aqui é listar somente os IDs, mas apenas das pessoas que sobreviveram. Como podemos fazer isso? A resposta é: adicionando uma condicional if. Quando o parâmetro 2 for igual a 1, significa que sobreviveu, e, se sobreviveu, podemos mostrar na tela. Nosso código fica assim:
cat gender_submission.csv | gawk 'BEGIN{FS=",";}{if ($2 == 1) print($1);}'
E pronto, você terá uma lista dos IDs desejados. Simples, não?
Você ainda pode jogar a saída para um arquivo:
(cat gender_submission.csv | gawk 'BEGIN{FS=",";}{if ($2 == 1) print($1);}') \
>> titanic_survivors_id.txt
Perceba que eu coloquei o comando para impressão de saídas em outra linha no shell para melhorar a visibilidade.
Melhorando o uso
Você pode também fazer a mesma coisa rodando os comandos diretamente de um arquivo. Como fazer isso? Vem comigo que eu vou te mostrar.
Primeiro escreva seu código todo dentro de um arquivo gs.awk:
BEGIN{
FS=",";
}
{
if ($2 == 1)
print($0);
}
E salve o arquivo na mesma pasta do arquivo. Agora, você pode rodar o comando assim:
cat gender_submission.csv | gawk -f gs.awk >> titanic_survivors_id.txt
Podemos simplificar ainda mais usando a hashbang. É só inserir a seguinte linha no topo do arquivo:
#!/bin/gawk -f
Seu código vai ficar assim:
#!/bin/gawk -f
BEGIN{
FS=",";
}
{
if ($2 == 1)
print($0);
}
Agora salve o arquivo e adicione permissão de execução ao arquivo:
chmod +x gs.awk
E pronto, seu comando ficará assim:
cat gender_submission.csv | ./gs.awk >> titanic_survivors_id.txt
Claro que existem infinitas outras melhorias que poderíamos fazer, como imprimir as linhas diretamente no arquivo correto, mas, para uma introdução, já foi bem interessante, concorda?
Projetos interessantes
Caso você queira estudar, existem vários projetos complexos que desafiam as limitações da linguagem, assim como tutoriais completos que exploram detalhes específicos da linguagem. Aqui vão alguns repositórios interessantes:
- AWK Raycaster: um jogo em estilo DOOM criado para rodar em terminal
- JSON.awk: um leitor de JSON escrito em AWK
- Opera Bookmarks: converte os dados das bookmarks do Chromium e derivados para SQLite e CSV
- AWKLISP: interpretador de LISP escrito em AWK
- learn_gnuawk: tutorial de AWK
- AHO: uma implementação completa do GIT escrita em AWK