Mostrando postagens com marcador Tutorial de AWK. Mostrar todas as postagens
Mostrando postagens com marcador Tutorial de AWK. Mostrar todas as postagens

Tutorial de AWK, parte 6: Aprenda a usar os Laços while e for, e como usar funções


- Loop while

O 'while' pode ser visto como uma série de testes condicionais 'if', pra entender melhor, basta traduzir do inglês (isso sempre ajuda): enquanto

awk 'BEGIN { while(++var <= 10) print var}'

Ou seja, ela incrementa a 'var' (por padrão, no inicio 'var=0') e imprime, até 'var=10'.
Veja o seguinte e tente interpretar você mesmo o que acontece:

awk 'BEGIN { while(var++ <=10 ) print var }'

(Se não estiver com um Shell por perto, o resultado é: 1, 2, …, 11. Sim, até 11. Por que?)


- Loop for

É um while com mais recursos, pois podemos especificar a condição inicial, a final e realizar alguma operação a cada iteraçao.

Aqui, a variável inicia em 1, só é válida enquanto for menor que 10 e é incrementada em 1 a cada iteração:

awk 'BEGIN {for(var=1 ; var <= 10 ; var++) print var }'


Realmente não há muito o que falar sobre if, while, for, do...provavelmente você já sabe, e a sintaxe é simplesmente a sintaxe da linguagem C.



- Funções


O AWK possui funções internas pra realizar conversão numérica, rodar comandos do sistema, mostrar hora, tamanho de uma string, funções matemáticas etc.

Por exemplo, vamos calcular o tamanho da frase que dá sentido ao universo:

awk 'BEGIN {print length("O vento do duende vem de roxo quando pisca na inconsciência do javali!")}'

Curiosidade: acentuação(',`,^,~) conta como caractere. Então tenha isso em mente caso precise da length.


A seguir, uma lista das funções mais comuns:


atan(x,y) arco-tangente de y/x, em radianos
cos(x) cosseno de x
sin(x) seno de x
exp() e^x
sqrt(x) raiz quadrada de x
index(strig,isso) procura na string 'string' a primeira ocorrencia da string 'isso'
int(x) menor inteiro próximo de x
length([string]) já usamos
rand() retorna um número entre 0 e 1
strftime(format) retorna o horario no mesmo formato da strftime(), do C
tolower(string) retorna a string minúscula
toupper(string) retorna a string maiúscula
system(command) executa um comando e retorna o exit code



- Mais informações


Código fonte do AWK:
ftp://ftp.gnu.org/pub/gnu/awk

AWK FAQ:
www.faqs.org/faqs/computer-lang/awk/faq/

Manuel completo do GNU AWK, gawk:
www.gnu.org/software/gawk/manual/gawk.html


Uma boa prática que deve ser mantida por quem costuma trabalhar com dados, textos e qualquer tipo informações, é a padronização.
De nada adianta você saber usar awk, sed, Perl, Python...se seus arquivos possuem informações desorganizadas.

Separe bem seus arquivos em pastas, com nomes dos arquivos bem expressivos, de preferência com conteúdo o mais simples e direto possível. Isso vai facilitar muito para, depois, você minar informações e agrupa-las.

Tutorial de AWK, parte 5: Operações Aritméticas/Matemática e Direcionamento da saída


- Operações Aritméticas

Já vimos como comparar variáveis, agora veremos como muda-las.
Isso pode ser feito através de adição, subtração, multiplicaçao, divisão e resto da divisão, inclusive com pontos flutuantes (float).

Por exemplo, para exibir o resultado de uma soma:

awk 'BEGIN {var=1 ; print var+var}'

O 'BEGIN' é porque, por padrão, o AWK espera um endereço de arquivo pra operar nele.
Nesse caso, como queremos apenas que o comando seja executado, sem a necessidade de um arquivo, usamos o 'BEGIN'. O restante é intuitivo.

Podemos, assim como em diversas outras linguagens, usar:
var=var+var 'var' dobra de valor
var++          'var' recebe 'var' e depois é incrementada (var=var+1)
++var          primeiro 'var' é incrementada, depois atribuída a ela própria incrementada
var1+=var2 é o mesmo que 'var1=var1+var2'


Pra entender melhor, faça e veja:
awk '
BEGIN
{
var=1;
var=var+var; print var;

var=0;
print var++;

var=0;
print ++var;

var1=1;
var2=2;
print var1+=var2;
}
    '

- Direcionando a saída

Ao invés de obter os resultados na tela, podemos passar esse resultado para um arquivo, exatamente como Shell faz.

Mas, aqui vai uma ressalva, o Shell usa '>' pra redirecionar a saída, assim como o AWK usa '>' como operador 'maior que'. Então, muito cuidado. Pra não ter erro, o nome do arquivo, que será a saída, estará entre aspas. Por exemplo:

awk 'BEGIN {print 1+1 > “resultado” }'

abra o arquivo resultado: cat resultado
que terá a resposta 2.

Porém, se já houver um arquivo chamado 'resultado', o AWK irá sobrescrever o dito cujo e todas as informações que estavam anteriormente lá serão perdidas.
Por via das dúvidas, utilize sempre o comando “>>”, que anexa o resultado ao fim do arquivo e caso este não exista, é criado.

akw 'BEGIN {print 2+2 >> “resultado”}'

cat resultado
2
4

Tutorial de AWK, parte 4: Testes Condicionais IF ELSE e Operadores Condicionais AND(&&) e OR(||)


São as instruções de controle que controlam o fluxo da execução dos programas em AWK.
Em AWK, elas são similares as de C, além de possuírem os mesmos loopings e iterações do padrão Shell.

Elas são: if, while, for, do e similares.

- if

Antes de estudarmos o 'if', vamos criar outro arquivo de texto, com números. Nesse arquivo, temos o nome de 4 pessoas, idade, há quanto tempo está no VOL(vivaolinux.com.br) e número de posts: vol.txt Neil 59 3 2112 Alex 30 5 578 Geddy 40 3 2789 Miulzo 24 1 134 Bom, quem teve o mínimo de contato com progração já sabe exatamente o que é o if. Então vamos printar na tela quem tem mais de 2mil posts: awk '{ if($4 > 2000) print $1 }' vol.txt Bem simples: se a condição 'if' for satisfeita, ele executa o próximo comando.
Fica mais fácil de fazer se separarmos esse comando em mais linhas. Veja:

awk '
 {
  if($4 < 2000)
   print $1
 }
' vol.txt

Geralmente, se deixa em uma linha quando o programa é pequeno ou estamos com preguiça.
Se for um pouco mais elobarado, colocamos num arquivo .AWK


Vamos agorar elaborar um programa com 'if', 'else' e 'strings' e salvar como: posts.awk
{
 if( $4 < 2000 )
  printf "%s postou menos de 2000 vezes\n", $1
 else
  printf "%s postou mais de 2000 vezes\n", $1
}
Executando: awk -f posts.awk vol.txt
Nesse programa, o AWK analisa cada linha, e o 4o campo de cada linha ($4, o número de posts).
Se for menor que 2mil, recai no 'if'.
Senão, recai no 'else'.


Embora tenha usado números no 'if', também poderíamos usar strings, como no script a seguir, enviado pelo usuário 'garoto-do-pintinho-piu':

#!/usr/bin/awk -f
{
 if( $1 == “pintinho” )
  printf “e o pintinho piu\n”
 else if( $1 == “galinha” )
  printf “a galinha có\n”
 else if( $1 == “galo” )
  printf “o galo corococó\n”
 else if( $1 == “peru” )
  printf “o peru glu glu\n”
 else if( $1 == “capote” )
  printf “o capote to fraco\n”
 else if( $1 == “gato” )
  printf “o gato miau\n”
 else
  printf “outro animal que quiser acrescentar\n”
}

Pronto, além de infernizar alguém pelo youtube, basta enviar um txt com uma lista de animais e mandar o .awk e infernizará seu amigo por linha de comando também, em AWK style.

Para rodar, torne o script executável: sudo chmod +x posts.awk
Rodando: ./posts.awk vol.txt

Ps: caso você não seja meu conterrâneo e do gordinho e quiser saber o que é capote, procure 'animal capote' no google, senão vai achar coisas sobre o autor Truman Capote ou sobre um, ótimo, filme chamado Capote (sobre o mesmo).

- Operadores

O '==' checa a condição de igualdade. Assim como '<', é chamado de operador de comparação.
Ei-los:
< Menor que
<=  Menor ou igual a
>  Maior que
>=  Maior ou igual a
!=  Diferente de
== Igual a

- Operadores && e ||

Para testar mais de uma condição, simultâneamente, usamos: && - E/AND || - OU/OR Por exemplos, vamos criar um programa para saber quem tem menos de 2mil posts e 30 anos ou menos: { if( ($4 < 2000) && ( $2 <= 30 ) ) printf “%s é noob na VOL”, $1 }
Se estiver com preguiça e quiser fazer na linha de comando e o programa não for tão imediato, faça como eu fiz, num editor de texto e com identação, pra ficar mais natural programar e depois vá apagando as quebras de linhas e espaços. Daí resta:

awk '{ if( ($4<2000) && ($2<=30) ) printf "%s é noob na VOL\n",$1}' vol.txt

Tutorial de AWK, parte 3: Usando as variáveis


- Variáveis definidas pelo usuário

Não podem começar variáveis por dígitos, elas são caso sensitivo, não devem ter o mesmo nome das variáveis do AWK nem de outros comandos e não precisam ser inicializadas ou declaradas.

Ao  usar pela primeira uma variável, ela é tanto uma string vazia(“”) como 0, mas não é muito bom confiar seu script nesses valores iniciais.

AWK é fracamente tipado, ou seja, você pode atribuir um número a uma variável e sem seguida atribuir uma string, por exemplo.

Ex: salvar como caes2.awk
BEGIN { nomecor="%-15s %20s\n"; printf nomecor, "Nome", "Cor\n"}
             { printf nomecor, $1, $2}

Inicialmente definimos o formato da varável 'nomecor', uma string alinha a esquerda e outra a direita.
Depois vamos imprimir as strings “Nome” e “Cor” nesse formato da 'nomecor'
Depois vamos imprimir, mas com os argumentos $1 e $2, aí o awk imprime linha a linha.

Pra rodar: awk -f caes2.awk caes.txt


- Variáveis internas

- FS
    FS significa "Field Separator" (separador de campo).
    é a variável que armazena o(s) caractere(s) separador(es) de campos.
    Usamos a flag -F, em exemplo anterior, para o caractere separador fosse a vírgula.
    Com a variável FS podemos escolher este caractere.

fs.awk :
BEGIN { FS=”,” }
{ printf “o %s é : %s\n”, $1,$2}

pra executar: awk -f fs.awk caes.txt

Essa variável é particularmente útil pois podemos definir o separador, não precisa ser somente um caractere. É como se você criasse sua própria expressão regular.
Se estivermos usando dados relacionados com valores de dinheiro: 9,99
Nesse caso não é bom usarmos a vírgula como separador, pois estaríamos separando o valor do real dos centavos.
Use espaço mesmo ou #, por exemplo: 1,99#2,99#3,99

A flexibilidade do FS advém do fato de podermos usar expressões regulares para expressar o 'field separator'. Por exemplo:

Para que o FS seja qualquer número de vírgula: FS="[,]+"
Para que o FS seja qualquer número de espaços: FS="[ ]+"
Para que o FS seja qualquer número de vírgula e qualquer número de espaço: FS="[,]+[ ]+"


Façam o teste com 1, 2, 3 e 4 vírgulas e espaços:
echo "1, 2,,  3,,,   4,,,,    " | awk 'BEGIN {FS="[,]+[ ]+"} {print $0}'

o echo que sai é o que é 'liberado' pela condição imposta no awk. Teste com $1, $2...


- NR
NR é uma variável que é automaticamente incrementada(em 1) em cada linha, pelo AWK.
Ele sempre contém o número da atual.

Teste-a:
awk '{print “Linha numero “,NR}' caes.txt

Pra aparecer o número total de linhas temos que fazer com que somente a última linha seja impressa, e isso pode ser feito com o comando END:
awk 'END {print “Total de linhas: ”,NR}' caes.txt

(Sim, eu sei que existe o comando 'wc', mas o que vale mais é a criatividade e se virar com o que se sabe)

Vamos usar a NR pra enumerar dados de um arquivo.
Salve como: coluna.awk

BEGIN { coluna=”%-10s %15s\n”;
         printf coluna, “Nome”, “Cor\n” }
     { printf “%d. “ coluna, NR, $1, $2 }

rode: awk -f coluna.awk caes.txt

Primeiros definimos a variável coluna, que será usad em todas linhas. Inicialmente a string coluna é imprimida com “Nome   Cor”.

Depois, imprimimos o número da linha seguido da string coluna: “%d. “ coluna,
O primeiro argumento, NR, vai pro “%d”, os outros dois, $1 e $2, vão pra variável coluna.
Note que a NR só começa depois do BEGIN.



A seguir, uma tabela-resumo das variáveis internas do AWK, para, caso te interesse, você saber sobre o que pesquisar:


ARGC, ARGV  Contém  número e o array dos argumentos passados pela linha de comando
CONVFMT  Controla a conversão de números para strings
ENVIRON  Array associativo com dados do sistema. O índices são os variáveis das variáveis do sistema
FILENAME  Contém o nome do arquivo que o awk está lendo
FNR  Número da gravação corrente, do arquiv corrente, que é incrementao pra cada linha lida
FS  Já vista no artigo
NF  Número de campos na linha de entrada atual
NR  Já vista no artigo
RS  Entrada do separador; a padrão é \n
OFS  Saída do separador de campo (NF)
ORS  Saída da RS
PROCINFO  Array contendo informações do arquivo, como “gid”, “uid”, “pid” e “version”

Tutorial de AWK, parte 2: Comandos Básicos




Vamos ao nosso primeiro programa em AWK:

awk '{ print “Tutorial de AWK - Site Linux Progressivo” }'

é preciso dar enter 2x para aparecer isso no console, pois o comando AWK espera mais um argumento, um filename.

Outra maneira de rodar esse programa é salvar:

{ print “Hello, World” }

em um arquivo .awk e usar o comando: awk -f hello.awk
a flag -f diz que o comando a seguir é um programa a ser executado.

Para um programa executável, usar o /usr/bin/awk:

world.awk:
#!/usr/bin/awk -f
# My first awk script

{ print “Hello, World!” }

Tornando esse arquivo executável: chmod +x world.awk
Executando: ./world.awk


- Comando print

Salve o arquivo: caes.txt
rex amarelo calmo magro
branco branco zangado         magro
lennon branco brincalhao gordo
fred branco zangado         gordo

Vamos imprimir na tela as linhas que acharem o trecho 're'

awk '{ /re/ print $0}' caes.txt

Mas o mesmo seria obtido em sed: cat caes.txt | sed -n '/re/p'

Em awk, porem, $0 imprime tudo.
$1 imprime o nome do cachorro, $2 a cor, $3 seu humor e $4 seu condicionamento físico!

Note como, de uma maneira esperta, o awk separou cada campo e enumerou-o.
Ele faz isso sempre que usamos espaço em branco.

Para obter o mesmo resultado, poderíamos:
awk '/re/' caes.txt
awk '/re/ {print $0}' caes.txt
awk '/re/ { print }'caes.txt

No que se nao especificarmos a string para aparecer no comando print, ele usa a $0.

Podemos usar essas variaveis dentro do comando print. Nele, sempre que colocamos uma vírgula, estamos espaçando:

awk '{print “O”,$1,”é”,$4}' caes.txt
o rex eh magro
o branco eh magro
o lennon eh gordo
o fred eh gordo

awk '{print “O”$1”é”$4}' caes.txt


- BEGIN

Com o begin, o AWK não espera por uma entrada (como digitar enter duas vezes), ele executa tudo daquele bloco:
awk 'BEGIN {print “Vai ser tudo \n imprimido \n de uma vez só\n”}'


- Outros separadores

Como vimos, o separador padrão do AWKé o espaço em branco (ou tab), no caes.txt
Porém, se eu tivesse um cão com o nome Neil Peart, o AWK interpretaria esse espaço como um separador, o que iria bagunçar tudo, pois minha intenção era que 'Neil Peart' inteiro fizesse parte do campo nome.

Em vez de separarmos por espaço, podemos separar por vírgula, que o AWK entenderá.

Salve o arquivo: caes2.txt
Neil Peart,branco,anti-social,em forma
rex,amarelo,calmo,magro
branco,branco,zangado,magro
lennon,branco,brincalhao,gordo
fred,branco,zangado,gordo
Usamos a flag -F pra informar ao awk que iremos usar a CSV (comma separeted values, valores separados por vírgula):

awk -F, '/re/ {print $1}' caes2.txt


- printf

Assim como na linguagem C, AWK também possui o comado printf, que é bem mais flexível que o print. A única coisa que o print faz que o printf não faz é colocar automaticamente uma nova linha ao final da string (\n).

awk '{ printf “Cor do cachorro %s: %s\n”, $1, $2}' caes.txt

Assim como em C, awk aceita os formatos: %c, %d e %i, %e e %E, %f, %g e %G, %o, %s, %u, %%,%x e %X.

Alinhamento à direita:
awk '{printf “|%10%s\n”,$1}' caes.txt

Alinhamento à esquerda:
awk '{printf “%-10s|\n”, $1}' caes.txt

Especificando quantos caracteres serão impressos (no caso, 3):
awk '{print “%.3s\n”, $1}' caes.txt


- fazendo um script em awk executar sobre um texto

Salvar o seguinte script como caes.awk
BEGIN { printf “%-10s %20s\n”, “Nome”, “Cor”}
{ printf “%-10s %20s\n”, $1, $2}

No terminal, digite:
awk -f caes.awk caes.txt


- sprintf

Ela age e tem a mesma sintaxe da printf. A diferença é que sua saída é armazenada em uma variável, ao invés de ser exibida na tela.

awk '{ variable = sprintf(“%-.3s”, $1); print variable}' caes.txt


Tutorial de AWK, parte 1: O que é e para que serve



AWK é uma linguagem de programação interpretada que é, geralmente, usada pra deixar os scripts de shell mais poderosos e com mais recursos. É usada mais pra processar dados nos textos e operações com arquivos.
O nome tem origem na primeira letra do sobrenome de cada um dos criadores: Alfred Aho, Peter Weinberger, and Brian Kernighan.

É relativamente simples e em pouco tempo é possível fazer coisas bem interessantes devido ao uso de expressões regulares e arrays associativos.

Assim como o sed, o AWK é stream-oriented, ou seja, trabalha linha por linha, que é mandada pro AWK e então algo é feito em cima daquela linha, retornando o resultado da operação naquela linha que você pediu.

Foi criada na década de 70 pela grande Bell Labs (que criou a linguagem C, a C++, o Unix, laser, transistor e várias outras coisas, a quais nós devemos a vida, inclusive 7 prêmios Nobel).

Ela é muito útil e prática, afinal foi feita pra ser usada em programas de uma linha na época do Pai Unix. Por isso podemos fazer várias coisas usando apenas meia-dúzia de comandos.

Quem já estudou C e/ou Perl (Larry se inspirou no awk) vai se sentir em casa.

Pra quem trabalha com dados e textos, nem preciso comentar o quão útil vai ser o AWK em sua vida.
Mas e se você não usa isso no trabalho, ou sequer trabalha, mas gosta do Linux, pra que serve?

Só te lembro uma coisa: os sistemas derivados do Unix são, em suma, uma grande string. Ou seja, é um texto bem grande. Pois é código aberto e praticamente tudo é arquivo de texto.
Uma distribuição do Linux tem mais de 200 milhões de linhas de código.

Logo, dominar o AWK é dominar a busca, extração, organização e substituição de informações do seu sistema. Pois não se vai atrás dos arquivos nas pastas, pois são muitos, além disso ser incômodo e chato.

Você pode achar qualquer coisa e obter informações do seu sistema com o AWK.
Sentiu o poder?