explicação do código awk

explicação do código awk

Recebi um código que deveria estar funcionando, mas não funciona, e estou tentando entender por que isso acontece. Estou tentando aprender bash e awk por esse motivo, mas é bastante confuso para mim. Se alguém pudesse me ajudar a entender esse código awk eu ficaria muito feliz.

cvgMids.txtcontém muitas linhas do seguinte formato

<http://rdf.freebase.com/ns/g.11b74p1stp>   <http://rdf.freebase.com/ns/type.object.type>   <http://rdf.freebase.com/ns/cvg.video_game_soundtrack>  .
<http://rdf.freebase.com/ns/g.11bc4msmrn>   <http://rdf.freebase.com/ns/type.object.type>   <http://rdf.freebase.com/ns/cvg.cvg_developer>  .
<http://rdf.freebase.com/ns/g.11bxxz28q6>   <http://rdf.freebase.com/ns/type.object.type>   <http://rdf.freebase.com/ns/cvg.computer_videogame> .
  • Qual é o sentido de BEGIN{i=0;}não ver a variável i sendo usada em nenhuma das linhas a seguir.

  • Para que é <(cat cvgMids.txt) <(gzip -dc freebase-rdf-latest.gz) > cvg_predicates.txt? Entendo que você colocou os arquivos no final do awk, mas está confuso para mim com todos esses parênteses etc.

awk 'BEGIN{i=0;}
FNR == NR {
    if($1 in a) next;
    a[$1] = $1;
    next
}
FNR<NR {
    if($1 in a) {print $0;}}' <(cat cvgMids.txt) <(gzip -dc freebase-rdf-latest.gz) > cvg_predicates.txt

Responder1

O que o snippet parece fazer é gerar as linhas do conteúdo descompactado freebase-rdf-latest.gzcujo primeiro campo delimitado por espaço em branco $1corresponde a qualquer um dos primeiros campos delimitados por espaço em branco de cvgMids.txt. No entanto, poderia ser escrito de forma mais simples.

Em particular:

  • como você observou, inão é usado em nenhum lugar, então o BEGINbloqueio pode ser eliminado

  • a sequência

    if($1 in a) next;
    a[$1] = $1;
    next
    

    poderia ser reduzido a

    a[$1];
    next
    

    (a matrizvaloresnunca são usados, apenas seus índices e é quase certamente tão eficiente reatribuir o índice várias vezes quanto testá-lo e atribuí-lo condicionalmente)

  • na regra-ação

    FNR<NR {
        if($1 in a) {print $0;}}
    

    você realmente não precisa, FNR<NRpois já tratou do caso FNR==NRe FNR>NRisso não vai acontecer 1 . Além disso, {print $0;}é a ação padrão. Então seria mais idiomático escrever

    $1 in a 
    
  • <(cat cvgMids.txt)e <(gzip -dc freebase-rdf-latest.gz)são cascasubstituições de processo. Funcionalmente, o primeiro é equivalente a cvgMids.txt(é ao mesmo tempo umUso inútil de gatoe um uso inútil de redirecionamento). Talvez tenha sido usado por razões estéticas.

Juntando tudo, obtemos

awk 'FNR == NR {a[$1]; next} $1 in a' cvgMids.txt <(gzip -dc freebase-rdf-latest.gz) > cvg_predicates.txt

Porém, se o original não funcionar, a versão simplificada também não funcionará.


1, a menos que seu código seja modificado FNRe/ou NR- o que é legal, mas raramente feito na prática.

informação relacionada