BEGIN e END com o comando awk

11

De acordo com o manual do awk, BEGIN e END não são usados para corresponder a entrada, mas para fornecer informações de inicialização e limpeza para o script do awk. Aqui está o exemplo dado:

ls -l | \
awk 'BEGIN { print "Files found:\n" } /\<[a|x].*\.conf$/ { print $9 }'
Files found:
amd.conf
antivir.conf
xcdroast.conf
xinetd.conf

Primeiro, imprime uma string para a saída. Em seguida, ele verifica a entrada para uma correspondência de padrão, em que a entrada começa com a ou x seguida por qualquer caractere, uma ou mais vezes, seguido pelo .conf. Para qualquer correspondência, a 9ª coluna é impressa.

O fato de que somos forçados a usar começa aqui, isso significa que o awk só pode usar no máximo uma função de impressão que contenha um BEGIN ou END? Se não, então por que não podemos simplesmente usar a função de impressão no início sem a palavra-chave BEGIN? Parece que o BEGIN é supérfluo.

    
por JohnMerlino 16.03.2014 / 05:41

4 respostas

9

O BEGIN não é supérfluo. Se você não especificar BEGIN , o print será executado para cada linha de entrada.

Citações do manual :

A BEGIN rule is executed once only, before the first input record is read. Likewise, an END rule is executed once only, after all the input is read.

$ seq 5 | awk 'BEGIN{print "Hello"}/4/{print}'   # Hello printed once
Hello
4
$ seq 5 | awk '{print "Hello"}/4/{print}'        # Hello printed for each line of input
Hello
Hello
Hello
Hello
4
Hello
$
    
por 16.03.2014 / 05:45
6

awk processa cada linha de entrada para as expressões fornecidas no corpo diferente de BEGIN e END blocks. No caso dos blocos BEGIN e END , awk processará as instruções apenas uma vez, antes que o processamento da entrada tenha começado e após o processamento da entrada ter sido feito respectivamente. Sem o bloco BEGIN , não apenas você não seria capaz de imprimir informações únicas, como cabeçalhos, você não conseguiria inicializar com eficiência algumas das variáveis exigidas pelo corpo. Além disso, FYI, um programa awk pode ter vários blocos BEGIN e END .

    
por 16.03.2014 / 05:45
2

awk executa todos os blocos somente quando o padrão antes dele coincidir. Padrão vazio (apenas bloco) corresponde a todas as linhas. BEGIN e END são padrões especiais que correspondem ao início e ao final do arquivo (análogo ao significado de ^ e $ na direção horizontal).

Se você deseja que algo seja executado antes de ler o arquivo, use BEGIN . Por exemplo, inicialização de contadores ou algo assim. END poderia então coletar os resultados.

    
por 16.03.2014 / 14:20
0

No exemplo dado, que eu acho que é simplificado para clareza pedagógica, você está certo de que é supérfluo. Você poderia obter os mesmos resultados sem usar BEGIN .

1 == NR            { print "Files found:\n" }
/\<[a|x].*\.conf$/ { print $9               }

produziria os mesmos resultados, já que a instrução print está restrita a apenas a primeira linha de entrada.

Dito isto, os blocos BEGIN e END são ferramentas incrivelmente poderosas. Como outras soluções mencionaram, você pode usar o bloco BEGIN para inicializar variáveis ou outras rotinas que precisam ser executadas apenas uma vez, mas também podem ser usadas para executar comandos do awk quando não houver arquivos para processar. Um exemplo simples:

BEGIN { print sqrt(12/4) }

Você pode ver um exemplo mais sério de programação no Awk sem processar nenhuma entrada aqui .

Da mesma forma, o bloco END é extremamente útil para realizar cálculos e resumir toda a entrada. Isso não pode ser feito (geralmente) sem a primeira leitura em todos os dados. Um exemplo simples de resumo de entrada pode ser encontrado aqui

    
por 17.03.2014 / 07:07

Tags