Tenho o seguinte awk
script que obtém o seguinte arquivo de entrada, input.txt
e produz a saída abaixo. Alguém pode, por favor, desmembrar como esse awk
script funciona? Eu gastei um pouco de tempo nisso e não está fazendo muito sentido.
Entrada:
$ cat input.txt
FINISHED RSYNCJOBNA 20140502 0021 2182096 2082096 6 5 2014820905820902 10:02:15 2014820905820902 10:56:42 0:54:27 INITIATED RSYNCJOBNA 20140502 0022 3282096 3182096 6 5 2014820905820902 15:31:06 0:06:04 ce eque**
Resultado:
RSYNCJOBNA|0021|20140502|10:02:15|10:56:42|0:54:27|FINISHED RSYNCJOBNA|0022|20140502|15:31:06| |0:06:04|INITIATED
Comando para obter a saída acima:
awk -v OFS="|" "/FINISHED|INITIATED/ { status = $1; getline; jobname = $1; getline; sequence = $2; date = $1; getline; start = $2; getline; if (status == "FINISHED") { end = $2; getline } else { end = " " } runtime = $1; print jobname, sequence, date, start, end, runtime, status; }" input.txt
Meu entendimento é que /FINISHED|INITIATED/ {}
significa que os comandos dentro das chaves só serão executados em linhas que correspondam a FINISHED
ou INITIATED
mas tanto quanto posso dizer pela saída, o script parece estar analisando todas as linhas. O que está acontecendo?
Comentários
Resposta
A função getline
lê a próxima linha e move o script para ela. chamadas getline
consecutivas passam para a próxima linha. Isso talvez seja mais fácil de entender com um exemplo:
$ cat input.txt foo 1 2 $ awk "/foo/{print; getline; print; getline; print}" input.txt foo 1 2
Como como você pode ver acima, o script processará a primeira linha porque corresponde a foo
. Cada chamada para getline
lerá a linha após a atual, então as print
chamadas subsequentes estão imprimindo as próximas linhas.
Resposta
Se você não sabe o que uma função awk
faz, então a estratégia usual é para dar uma olhada na página de manual:
getline
Defina $ 0 do próximo registro de entrada; defina NF, NR, FNR, RT
O bloco de comando é realmente executado apenas duas vezes. As outras linhas são tratadas via getline
de dentro do bloquear.
Isso pode ser reescrito para:
/FINISHED|INITIATED/ { status = $1; line_number=0; next; } { line_number++; } line_number==1 { jobname = $1; } line_number==2 { sequence = $2; date = $1; } ...
Comentários
- O que acontece se o próximo registro estiver vazio?
- @AvinashRaj Nem o seu código nem a minha alternativa examinam o conteúdo das linhas (com exceção de
/FINISHED|INITIATED/
). As linhas são apenas contadas. Os dados devem ser organizados exatamente (de um parsi de awk perspectiva) da maneira que você mostrou, caso contrário, o código irá quebrar.
/FINISHED|INITIATED/
, awk procura a linha correspondente e faz a operação apenas naquela linha particular. Mas a operação foi realizada em todas as linhas. Como?