Ch1
Table of Contents
1 Getting Started
Suponha que tenhamos um arquivo que contenha o nome, o salário por hora e quantas horas foram trabalhadas chamado "emp.data":
Beth 4.00 0
Dan 3.75 0
Kathy 4.00 10
Mark 5.00 20
Mary 5.50 22
Susie 4.25 18
Agora, queremos imprimir o nome e quando deve ser pago a cada empregado que trabalhou:
$3 > 0 { print $1, $2 * $3}
Pode-se fazer direto da linha de comando com: $ gawk '$3 > 0 { print $1, $2 * $3 }' emp.data
Ambos imprimem: Kathy 40
Mark 100
Mary 121
Susie 76.5
O programa é muito simples, é um "pattern-action statement": o padrão $3 > 0 é satisfeito por todas as linhas cuja terceira coluna é maior que 0 e, então, é executado o bloco entre {}.
1.1 A estrutura de um programa awk
Nesse capítulo, os programas são todos da forma: pattern { action }
pattern { action }
pattern { action }
…
Toda linha de input é testada para todos os padrões.
Tanto o padrão como a ação podem ser omitidos (claramente não ao mesmo tempo). Se um padrão não possui ação, todas as linhas (ou o outro divisor) que satisfazem o padrão serão impressas. Por exemplo, no arquivo emp.data, o programa '$3 == 0' imprime as linhas da Beth e do Dan. Um ação sem padrão é executada para todas as linhas.
2 Output Simples
Existem dois tipos de dados em awk: números e strings.
O awk lê o input uma linha por vez e a quebra em campos, que são, por default, uma sequência de caracteres que não contém whitespace.
O primeiro campo é denotado por $1, o segundo por $2 e assim por diante. A linha inteira é denotada por $0.
2.1 NF
A variável NF armazena o número de campos na linha atual. Logo, o programa
{ print NF, $1, $NF }
imprime o número de campos, o primeiro e o último campo de cada linha.
2.2 NR
Outra variável built-in é NR, que armazena o número de linhas lidas até o momento. O programa a seguir imprime cada linha com seu número na frente:
{ print NR, $0 }
No caso do arquivo emp.data, a saída é 1 Beth 4.00 0 2 Dan 3.75 0 3 Kathy 4.00 10 4 Mark 5.00 20 5 Mary 5.50 22 6 Susie 4.25 18
3 Output com frescuras
Pode-se usar printf.
O livro diz que para se ordenar a saída é para usar um pipe com sort. Eu diria que é justo.
4 Seleção
4.1 Regex
São indicadas por "/ /". O padrão Susie imprime as linhas que contém Susie.
4.2 Operadores lógicos
Os mesmos operadores lógicos de C podem ser usados nos padrões.
4.3 BEGIN e END
O padrão BEGIN é executado antes da leitura da primeira linha e o padrão END ao fim da leitura.
Por exemplo, o programa
BEGIN { print "NAME RATE HOURS"; print "" } {print}
Imprime um cabeçalho.
5 Computing com awk
5.1 Contando
O programa a seguir usa a variável emp para contar os empregados que trabalharam mais de 15hs:
$3 > 15 { emp = emp + 1 } END { print emp, "employees worked more than 15 hours"}
5.2 Texto
As variáveis de awk podem armazenar strings ou números:
$2 > maxrate { maxrate = $2; maxemp = $1 } END { print "highest hourly rate:", maxrate, "for", maxemp }
5.3 Concatenação de Strings
Strings são concatenadas simplesmente escrevendo-as uma do lado da outra.
{ names = names $1 " " } END { print names }
5.4 Funções built-in
As matemáticas padrão e algumas para texto. Uma útil é "length" que é o número de caracteres numa string.
6 Fluxo
6.1 if - else, for, while
C-like.
7 Arrays
# reverse - output = input in reverse order by line { line[NR] = $0 } # armazena a linha END { i = NR while (i > 0) { print line[i] i = i - 1 } }
8 One-liners
# Número de linhas END { print NR } # Imprime a décima linha NR == 10 # Imprime o último campo de cada linha { print $NF } # Imprime o último campo da última linha { campo = $NF } END { print campo } # Imprime toda linha com mais de quatro campos NF > 4 # Imprime toda linha cujo último campo é maior que 4 $NF > 4 # Imprime o número total de campos na entrada { nf = nf + NF } END { print nf } # Imprime quantas linhas tem "palavra" /palavra/ { nlines = nlines + 1} END { print nlines } # Imprime o maior primeiro campo e a linha que o contém $1 > max { max = $1; maxline = $0 } END {print max, maxline } # Imprime toda linha com pelo menos um campo NF > 0 # Imprime toda linha com mais de 80 caracteres length($0) > 80 # Imprime o número de campos da linha seguido da linha { print NF, $0 } # Imprime os dois primeiros campos, o segundo antes do primeiro { print $2, $1 } # Troca os dois primeiros campos e imprime a linha { temp = $1; $1 = $2; $2 = temp; print } # Imprime toda linha com o primeiro campo substituído pelo número da linha { $1 = NR; print } # Imprime toda linha sem o segundo campo { $2 = ""; print } # Imprime os campos em ordem reversa { for (i = NF; i > 0; i = i - 1) printf("%s ", $i) printf("\n") } # Imprime a soma dos campos { sum = 0 for (i = 1; i <= NF; i = i + 1) sum = sum + i print sum } # Soma todas os campos de todas as linhas { for (i = 1; i <= NF; i = i + 1) sum = sum + $i } END { print sum } # Imprime toda linha substituindo seus campos pelo seu valor absoluto { for (i = 1; i <= NF; i = i + 1) if ($i < 0) $i = -$i print }