Bloco condicional vs instrução condicional (se)

17

Digamos que eu tenho um arquivo:

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

Eu quero que cada linha que tenha 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 bem:

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

Mas quando eu uso o bloco condicional, algo indesejado 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 corrijo esse erro?
  • Por que esse erro ocorre?
  • Qual é a diferença entre uma declaração condicional e um bloco condicional?
Ooker
fonte

Respostas:

26

Em uma ifdeclaração, você tem um else. Se ifnão corresponder, o elseramo será executado.

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

Uma correçã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 é verdadeira 1e não há ação, awko comportamento padrão é print. printsem argumento será impresso $0por padrão.

cuonglm
fonte
4
Você também pode jogar awk '$2!=1?$2=0:"";1' file.
terdon
@terdon: Bom golfe. Eu acho que pode ser difícil OP entender isso.
18714 cu Cullm
1
@cuonglm você poderia explicar o papel de next. Acho que suprime a segunda impressão, se a primeira for verdadeira. Algo como continueem C.
Alexander Cska
@ Alexander Cska: nextsuprime a linha de entrada atual de processamento, pule para a próxima. O mesmo papel que while, mas para todo o awkprograma. Além disso, awktem o seu própriowhile
cuonglm
10

O segundo bloco em

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

não é condicional. Ele é acionado para cada linha e, assim, imprime todas as linhas.

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.

Kyle Jones
fonte