Sig, at jeg har en fil:
PRO 1 GLN 5.55112e-17 ILE -6.245e-17 THR 5.55112e-17
Jeg vil have, at hver linje, der har et tal, der ikke er lig med 1 i anden kolonne, skal ændre det til 0 og beholde resten.
Hvis jeg bruger if
(dvs. betinget erklæring), alt er OK:
awk "{if($2!=1){print $1,"0"}else{print $0}}" file PRO 1 GLN 0 ILE 0 THR 0
Men når jeg bruger den betingede blok, sker der noget uønsket:
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, hvad der er forkert.
- Hvordan løser jeg denne fejl?
- Hvorfor opstår denne fejl?
- Hvad er forskellen mellem en betinget erklæring og en betinget blok?
Svar
I en if
udsagn, du har en else
. Hvis if
ikke stemmer overens, udføres else
-grenen.
I en betinget erklæring er begge handlinger udført, uanset om betingelsen er sand eller falsk.
En simpel løsning:
$ awk "$2!=1 {print $1,"0";next};{print $0}" file PRO 1 GLN 0 ILE 0 THR 0
Og du kan gøre det mere kortfattet:
$ awk "$2 != 1 {print $1,"0";next};1" file PRO 1 GLN 0 ILE 0 THR 0
Når betingelsen er sand 1
og der ikke er nogen handling, awk
standardadfærd er print
. print
uden argument udskrives $0
som standard.
Kommentarer
Svar
Den anden blok i
awk "$2!=1 {print $1,"0"} {print $0}" file
er ikke betinget. Den handles for hver linje og udskriver således hver linje.
Skriv i stedet:
awk "$2!=1 {print $1,"0"} $2==1 {print $0}" file
Eller skriv:
awk "$2!=1 {print $1,"0"; next} {print $0}" file
Dette springer over den ubetingede blok, hvis den betingede blok matches.
awk '$2!=1?$2=0:"";1' file
.next
. Jeg antager, at det undertrykker det andet tryk, hvis det første er sandt. Noget somcontinue
iC
.next
undertrykker behandlingen af den aktuelle inputlinje, spring til den næste. Den samme rolle somwhile
, men for heleawk
-programmet.awk
har også sit egetwhile