Blok bersyarat vs pernyataan kondisional (jika)

17

Katakanlah saya punya file:

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

Saya ingin setiap baris yang memiliki angka tidak sama dengan 1 di kolom kedua untuk mengubahnya menjadi 0 dan menyimpan sisanya.

Jika saya menggunakan if(yaitu pernyataan kondisional), semuanya OK:

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

Tetapi ketika saya menggunakan blok bersyarat, sesuatu yang tidak diinginkan terjadi:

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

Anda dapat melihat apa yang salah.

  • Bagaimana cara saya memperbaiki kesalahan ini?
  • Mengapa kesalahan ini terjadi?
  • Apa perbedaan antara pernyataan bersyarat dan blok bersyarat?
Ooker
sumber

Jawaban:

26

Dalam sebuah ifpernyataan, Anda memiliki else. Jika iftidak cocok, elsecabang dijalankan.

Dalam pernyataan bersyarat, kedua tindakan dijalankan, terlepas dari kondisinya benar atau salah.

Perbaikan sederhana:

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

Dan Anda bisa membuatnya lebih ringkas:

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

Ketika kondisi benar 1dan tidak ada tindakan, awkperilaku default adalah print. printtanpa argumen akan mencetak $0secara default.

cuonglm
sumber
4
Anda juga bisa memasukkannya ke dalam golf awk '$2!=1?$2=0:"";1' file.
terdon
@terdon: Golf yang bagus. Saya pikir OP bisa sulit untuk memahaminya.
cuonglm
1
@cuonglm bisa tolong jelaskan peran next. Saya kira ini akan menekan cetakan kedua jika yang pertama benar. Sesuatu seperti continuedi C.
Alexander Cska
@Alexander Cska: nextmenekan pemrosesan jalur input saat ini, lewati ke yang berikutnya. Peran yang sama dengan while, tetapi untuk keseluruhan awkprogram. Juga, awkmemiliki sendiriwhile
cuonglm
10

Blok kedua masuk

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

tidak bersyarat. Itu ditindaklanjuti untuk setiap baris, dan dengan demikian mencetak setiap baris.

Sebaliknya, tulis:

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

Atau tulis:

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

Ini akan menyebabkan blok bersyarat dilewati, jika blok bersyarat cocok.

Kyle Jones
sumber