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?

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.


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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.