Säg att jag har en fil:
PRO 1 GLN 5.55112e-17 ILE -6.245e-17 THR 5.55112e-17
Jag vill att varje rad som har ett tal som är lika med 1 i den andra kolumnen ska ändra det till 0 och behålla resten.
Om jag använder if
(dvs. villkorligt uttalande), allt är OK:
awk "{if($2!=1){print $1,"0"}else{print $0}}" file PRO 1 GLN 0 ILE 0 THR 0
Men när jag använder det villkorliga blocket händer något oönskat:
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
Du kan se vad som är fel.
- Hur fixar jag det här felet?
- Varför uppstår detta fel?
- Vad skiljer sig mellan ett villkorligt uttalande och ett villkorligt block?
Svar
I en if
uttalande, du har ett else
. Om if
inte överensstämmer, körs grenen else
.
I ett villkorligt uttalande är båda åtgärderna körs, oavsett om villkoret är sant eller falskt.
En enkel fix:
$ awk "$2!=1 {print $1,"0";next};{print $0}" file PRO 1 GLN 0 ILE 0 THR 0
Och du kan göra det mer kortfattat:
$ awk "$2 != 1 {print $1,"0";next};1" file PRO 1 GLN 0 ILE 0 THR 0
När villkoret är sant 1
och det finns ingen åtgärd, awk
standardbeteende är print
. print
utan argument skrivs ut $0
som standard.
Kommentarer
Svar
Det andra blocket i
awk "$2!=1 {print $1,"0"} {print $0}" file
är inte villkorligt. Det handlas för varje rad och skrivs alltså ut varje rad.
Skriv istället:
awk "$2!=1 {print $1,"0"} $2==1 {print $0}" file
Eller skriv:
awk "$2!=1 {print $1,"0"; next} {print $0}" file
Detta hoppar över det ovillkorliga blocket om det villkorliga blocket matchas.
awk '$2!=1?$2=0:"";1' file
.next
. Jag antar att det undertrycker den andra utskriften om den första är sant. Något somcontinue
iC
.next
undertrycker bearbetning av den aktuella inmatningsraden, hoppa till nästa. Samma roll somwhile
, men för helaawk
-programmet. Dessutom harawk
sitt egetwhile