[ UNIX ]
awk
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 |
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 :
<= |