Powiedz, że mam plik:
PRO 1 GLN 5.55112e-17 ILE -6.245e-17 THR 5.55112e-17
Chcę, aby każda linia, która ma liczbę nierówną 1 w drugiej kolumnie, zmieniła ją na 0 i zachowała resztę.
Jeśli użyję if
(tj. instrukcja warunkowa), wszystko jest w porządku:
awk "{if($2!=1){print $1,"0"}else{print $0}}" file PRO 1 GLN 0 ILE 0 THR 0
Ale kiedy używam bloku warunkowego, dzieje się coś niepożądanego:
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
Możesz zobaczyć, co jest nie tak.
- Jak naprawić ten błąd?
- Dlaczego występuje ten błąd?
- Czym różni się instrukcja warunkowa od bloku warunkowego?
Odpowiedź
W if
, masz else
. Jeśli if
nie pasuje, wykonywana jest gałąź else
.
W instrukcji warunkowej obie akcje są wykonywany niezależnie od tego, czy warunek jest prawdziwy czy fałszywy.
Prosta poprawka:
$ awk "$2!=1 {print $1,"0";next};{print $0}" file PRO 1 GLN 0 ILE 0 THR 0
I możesz uczynić to bardziej zwięzłym:
$ awk "$2 != 1 {print $1,"0";next};1" file PRO 1 GLN 0 ILE 0 THR 0
Gdy warunek jest prawdziwy 1
i nie ma żadnego działania, awk
domyślne zachowanie to print
. print
bez argumentu domyślnie wypisze $0
.
Komentarze
Odpowiedź
Drugi blok w
awk "$2!=1 {print $1,"0"} {print $0}" file
nie jest „t warunkowy. Jest wykonywany dla każdego wiersza i dlatego wypisuje każdy
Zamiast tego napisz:
awk "$2!=1 {print $1,"0"} $2==1 {print $0}" file
Lub napisz:
awk "$2!=1 {print $1,"0"; next} {print $0}" file
Spowoduje to pominięcie bloku bezwarunkowego, jeśli zostanie dopasowany blok warunkowy.
awk '$2!=1?$2=0:"";1' file
.next
. Myślę, że to tłumi drugi wydruk, jeśli pierwszy jest prawdziwy. Coś w rodzajucontinue
wC
.next
wstrzymuje przetwarzanie bieżącej linii wejściowej, przeskakuje do następnej. Ta sama rola cowhile
, ale dla całego programuawk
. Ponadtoawk
ma własnąwhile