Bloco condicional vs declaração condicional (if)

Digamos que eu tenha um arquivo:

PRO 1 GLN 5.55112e-17 ILE -6.245e-17 THR 5.55112e-17 

Quero que cada linha com um número diferente de 1 na segunda coluna mude para 0 e mantenha o resto.

Se eu usar if (ou seja, declaração condicional), está tudo OK:

awk "{if($2!=1){print $1,"0"}else{print $0}}" file PRO 1 GLN 0 ILE 0 THR 0 

Mas quando uso o bloco condicional, algo indesejável acontece:

awk "$2!=1 {print $1,"0"} {print $0}" file PRO 1 GLN 0 GLN 5.55112e-17 ILE 0 ILE -6.245e-17 THR 0 THR 5.55112e-17 

Você pode ver o que está errado.

  • Como faço para corrigir esse erro?
  • Por que esse erro ocorre?
  • Qual é a diferença entre uma declaração condicional e um bloco condicional?

Resposta

Em um if declaração, você tem uma else. Se if não corresponder, o else branch é executado.

Em uma instrução condicional, ambas as ações são executado, independentemente de a condição ser verdadeira ou falsa.

Uma solução simples:

$ awk "$2!=1 {print $1,"0";next};{print $0}" file PRO 1 GLN 0 ILE 0 THR 0 

E você pode torná-lo mais conciso:

$ awk "$2 != 1 {print $1,"0";next};1" file PRO 1 GLN 0 ILE 0 THR 0 

Quando a condição for verdadeira 1 e não houver ação, awk o comportamento padrão é print. print sem nenhum argumento imprimirá $0 por padrão.

Comentários

  • Você também pode jogar golfe em awk '$2!=1?$2=0:"";1' file.
  • @ terdon: Bom golfe. Acho que pode ser difícil para o OP entender isso.
  • @cuonglm, você poderia explicar o papel de next. Acho que suprime a segunda impressão se a primeira for verdadeira. Algo como continue em C.
  • @Alexander Cska: next suprime o processamento da linha de entrada atual, pule para a próxima. A mesma função de while, mas para todo o programa awk. Além disso, awk tem sua própria while

Resposta

O segundo bloco em

awk "$2!=1 {print $1,"0"} {print $0}" file 

não é condicional. Ele é executado em cada linha e, portanto, imprime cada linha.

Em vez disso, escreva:

awk "$2!=1 {print $1,"0"} $2==1 {print $0}" file 

Ou escreva:

awk "$2!=1 {print $1,"0"; next} {print $0}" file 

Isso fará com que o bloco incondicional seja pulado, se o bloco condicional for correspondido.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *