[ UNIX ]
awk  



Introdução
awk é derivado do sobrenome de seus autores Aho, Weinberger e Kernighan, é uma linguagem de programação que facilita a manipulação de estruturas de dados e geração de relatórios formatado, awk possui operadores relacionais e boleanos, condicionais, loops, arrays, funcções aritiméticas, funções de string além de permitir que você escreva suas própias funções. Este artigo é uma breve introdução ao awk, para um maior aprofundamento veja as referências. Existem várias versões do awk, algumas freeware e outras comerciais além da definida pelo padrão POSIX.

A forma geral para usar o programa é  awk '{comandos}'. Existem três flags possíveis para awk: -f arq especifica que as intruções devem ser lidas do arquivo arq e não da linha de comando, emquanto -Fc indica que o programa deve considerar a letra c como o separador entre campos de informação, em vez de usar o padrão de espaços em branco (um ou mais espaços ou caracteres de tabulação) e o flag -v.

O primeiro comando que vamos ver é o print usado sem argumento ele imprime as linhas do arquivo uma a uma:

    % who | awk '{ print }'
    frank        tty01    Apr    3    02:20
    joaquim    tty03    Apr    3    02:45
    naurimar   tty04    Apr    3    03:00

A cada linha de saída é atribuido um identificado único, assim o campo u é $1, o campo 2 é $2, e assim por diante:

    %who | awk '{ print $1 }'
    frank
    joaquim
    naurimar

Você pode especificar textos para serem impressos, basta envolvelos com aspas duplas:

    %who | awk '{ print "O usuario " $1 " logou as " $3 " no terminal " $2 }'
    O usuario frank        logou as 02:20    no terminal tty01
    O usuario joaquim    logou as 02:45    no terminal tty03
    O usuario naurimar   logou as 03:00    no terminal  tty04

Agora vamos ver um exemplo usando o arquivo  passwd juntamente com o flag -Fc  :

    %grep naurimar /etc/passwd | awk -F: '{ print $1 " esta usando " $7 " como shell de login." }
    naurimar esta usando /bin/csh como shell de login

Vamos ver mais um exemplo, vamos supor que você queira saber quantos tipos de shell são usados no seu sistema e qual é o mais utilizado:

    % awk -F: '{ print $7}'  /etc/passwd | sort | uniq -c
    10    /bin/csh
      3    /bin/ksh
      9    /bin/sh
    12    /bin/tcsh
      5    /usr/sbin/csh

    Primeiro usamos o awk para extrair o sétimo campo, a saida foi redirecionada para o comando sort e em seguida usamos o comando uniq -c realiza-se a contagem de ocorrências.

O script anterior que procurou pelo shell de login não está completamente correto. Ela não funciona, pois, se o usuário quiser ter /bin/sh como seu shell padrão, o campo final pode ser deixado em branco:

    tadeu:*:32:333:Tadeu Barros:/home/tadeu:

$0, $NF, NF e NR
Isso pode trazer um problema, pois o campo em branco confundirá o programa awk; awk está apenas contando os campos na linha. A variável NF amarzena o número de campos em uma linha. Usanda sem o sinal de dolar ela indica o número de campos em uma linha, com o sinal de dolar ela indica o valor do último campo na linha, assim:

    % who | head -3 | awk '{ print NF }'
    5
    5
    5

    %who | head -3 | awk '{ print $NF }'
    02:20
    02:45
    03:00

Estamos interessados no último campo do arquivo passwd, então podemos usar o parametro $NF:

    % awk -F: '{ print $NF}'  /etc/passwd | sort | uniq -c
     10    /bin/csh
      3    /bin/ksh
    16    /bin/sh
    12    /bin/tcsh
      5    /usr/sbin/csh

A variável NR guarda o número de linhas exibidas e o campo zero ( $0 ) corresponde a linha interira:

    % ls -alp | awk '{ print NR " : " $0 }'
    1:    total 4
    2:    drwxrwxr-x    2    joaquim    512    Apr    03    02:45    .
    3:    drwxrwxr-x    2    joaquim    512    Apr    03    02:25    ..
    4:    -rw-r--r--      2    joaquim   1102    Apr    03    03:35    verifica.sh *
    5:    drwxrwxr-x    3    joaquim    512    Apr    03    03:50    temp /
    6:    drwxrwxr-x    3    joaquim    512    Apr    03    03:55    aux /
    7:    -rwxrwxr-x    2    joaquim   2120    Apr    03    02:50    mail.sh

Agora vamos rapidamente listar o nome do arquivo e seu tamaho:

    % ls -lF | awk '{ print $9 " " $4 }'
    verifica.sh 1102
    temp/  512
    aux/ 512
    mail.sh 2120

Você pode melhorar a saida usando a seqüência de caracteres especiais :
    \n    retorno de carro
    \t    tabulação

% ls -lF | awk '{ print $9 "\t" $4 }'
    verifica.sh    1102
    temp/            512
    aux/              512
    mail.sh        2120

Veja como listar os quatro arquivos maiores:

    % ls -l | awk '{ print $4 "\t"$9 }' | sort -rn | head -4
    mail.sh        2120
    verifica.sh   1102
    aux/              512
    temp/            512

    OBS: o flag -n do sort indica classificacao numérica e o flag -r é para reverter a classificação do maior para o menor.

O programa awk basicamente procura por um padrão para aparecer em uma linha e, se o encontrar, executa as instruções que seguem o padrão no script awk. Há dois padrões especiais em awk: BEGIN e END. As instruções que seguem BEGIN são executadas antes que quaisquer linhas de saída sejam lidas. As instruções que seguem END são executadas apenas depois de todas as saídas terem sido lidas. Isso pode ser útil para computar uma série de números. Vamos calcular o número de bytes usados por todos os arquivos:

    % ls -l | awk '{ print $4 }'
    1102
      512
      512
    2120

Isso gera a lista de tamanhos de arquivos, mas como somá-los? Uma forma válida é criar uma nova variável total e promover a saída de seu valor acumulado depois de cada linha:

    % ls -l | awk '{ total = total + $4; print total }'
      512
    1024
    2126
    4266

A instrução total = total + $4, pode ser subistituida por total += $4:

    % ls -l | awk '{ total += $4; print total }'
     512
    1024
    2126
    4266

Podemos usaro comando tail para obter a última linha e calcular o tamanho total :

    % ls -l | awk '{ total += $4; print total }' | tail -1
     4266

Entretanto , uma forma mais pratica é usar o bloco de programação END:

    % ls -l | awk '{ total += $4 } END { print total }'
    4266

Vamos colocar um pouco de cor a nossa saida: :)

    % ls -l | awk '{ total += $4 } END { print "Voce tem um total de " total " bytes usados em " NR  " arquivos" }'
    Voce tem um total de 4266 bytes usados em 4 arquivos

Você pode criar um script para fazer isso, veja:

    % cat << EOF total.scp
                {  total += $4 }
    END    { print "Voce tem um total de " total " bytes usados em " NR  " arquivos" }
    EOF

    % ls -l | awk -f total.scp
    Voce tem um total de 4266 bytes usados em 4 arquivos

Operadores relacionais
Operadores relacionais e boleanos permitem que você faça comparações entre duas expressões. Agora vamos tratar dos operadores relacionais.
 
Operador Descrição
  <   Menor que
  >   Maior que
  <=  Menor que ou igual a
  >=   Maior que ou igual a
  = =   Igual a
  !=   Diferente de
  ~   Contém
  !~   Não contém
Vejamos alguns exemplos:

Verifica se nas linhas de entrada vindas do arquivo passwd o primeiro campo ($1) é igual a maristela. Se a condição for verdadeira a função print imprime a linha toda, comparação com strings devem estar entre aspas duplas.

    % cat /etc/passwd | awk -F: ' $1  = =  "maristela" { print }'
    % maristela:*:32:333:Maristela Holanda:/home/maristela:csh

O operador  ~  pesquisa um fragmento de texto dentro de uma linha. No exemplo acima, pesquisa se o fragmento riste está contido no primeiro campo das linhas de entrada.

    % cat /etc/passwd | awk -F: ' $1 ~ /riste/  { print $1 ", " $6 }'
    % maristela, /home/maristela

Além de fragmentos puros você pode usar expressões regulares, vejamos mais um exemplo:
Verifica se nas linhas de entranda o primeiro campo possui o nome Paulo e/ou paulo.

    % cat /etc/passwd | awk -F: ' $1 ~ /[Pp]aulo/  { print $1 ", " $6 }'
    % paulo, /home/paulo
 

Referência :


<=

http://www.absoluta.org      ---oOo---      verdade@absoluta.org

Copyright © 1998 - 2000  Verdade @bsoluta