Blocco condizionale vs istruzione condizionale (se)


17

Di 'che ho un file:

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

Voglio che ogni riga che abbia un numero diverso da 1 nella seconda colonna lo cambi in 0 e mantenga il resto.

Se uso if(cioè un'istruzione condizionale), va tutto bene:

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

Ma quando uso il blocco condizionale, succede qualcosa di indesiderato:

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

Puoi vedere cosa c'è che non va.

  • Come posso correggere questo errore?
  • Perché si verifica questo errore?
  • Qual è la differenza tra un'istruzione condizionale e un blocco condizionale?

Risposte:


26

In una ifdichiarazione, hai un else. Se ifnon corrisponde, il elseramo viene eseguito.

In un'istruzione condizionale, entrambe le azioni vengono eseguite, indipendentemente dal fatto che la condizione sia vera o falsa.

Una semplice soluzione:

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

E puoi renderlo più conciso:

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

Quando la condizione è vera 1e non vi è alcuna azione, awkil comportamento predefinito è print. printsenza alcun argomento verrà stampato $0per impostazione predefinita.


4
Puoi anche giocare a golf awk '$2!=1?$2=0:"";1' file.
terdon

@terdon: buon golf. Penso che possa essere difficile da capire per OP.
cuonglm,

1
@cuonglm potresti per favore spiegare il ruolo di next. Immagino che sopprima la seconda stampa se la prima è vera. Qualcosa di simile continuea C.
Alexander Cska,

@Alexander Cska: nextelimina l'elaborazione della riga di input corrente, passa a quella successiva. Lo stesso ruolo di while, ma per l'intero awkprogramma. Inoltre, awkha il suowhile
cuonglm

10

Il secondo blocco in

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

non è condizionale. Viene applicato per ogni riga e quindi stampa ogni riga.

Invece, scrivi:

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

Oppure scrivi:

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

Ciò causerà il blocco incondizionato del blocco, se il blocco condizionale è abbinato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.