Bloque condicional vs declaración condicional (si)

Digamos que tengo un archivo:

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

Quiero que cada línea que tenga un número diferente a 1 en la segunda columna lo cambie a 0 y mantenga el resto.

Si uso if (es decir declaración condicional), todo está bien:

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

Pero cuando uso el bloque condicional, sucede algo no deseado:

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 

Puede ver lo que está mal.

  • ¿Cómo soluciono este error?
  • ¿Por qué ocurre este error?
  • ¿Cuál es la diferencia entre una declaración condicional y un bloque condicional?

Responder

En una if declaración, tiene una else. Si if no coincide, se ejecuta la rama else.

En una declaración condicional, ambas acciones son ejecutado, independientemente de que la condición sea verdadera o falsa.

Una solución simple:

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

Y puede hacerlo más conciso:

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

Cuando la condición es verdadera 1 y no hay acción, awk el comportamiento predeterminado es print. print sin argumento se imprimirá $0 de forma predeterminada.

Comentarios

  • También puedes jugar al golf en awk '$2!=1?$2=0:"";1' file.
  • @ terdon: Buen golf. Creo que puede ser difícil para OP entender eso.
  • @cuonglm, ¿podría explicar el papel de next. Supongo que suprime la segunda impresión si la primera es verdadera. Algo como continue en C.
  • @Alexander Cska: next suprime el procesamiento de la línea de entrada actual, pase a la siguiente. La misma función que while, pero para todo el programa awk. Además, awk tiene su propia while

Respuesta

El segundo bloque en

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

no es condicional. Se actúa sobre él para cada línea y, por lo tanto, imprime cada línea.

En su lugar, escriba:

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

O escriba:

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

Esto hará que se omita el bloque incondicional, si el bloque condicional coincide.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *