Bedingter Block gegen bedingte Anweisung (if)

Angenommen, ich habe eine Datei:

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

Ich möchte, dass jede Zeile mit einer Zahl ungleich 1 in der zweiten Spalte diese in 0 ändert und den Rest behält.

Wenn ich if verwende (dh bedingte Anweisung), alles ist in Ordnung:

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

Wenn ich jedoch den bedingten Block verwende, passiert etwas Unerwünschtes:

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 

Sie können sehen, was falsch ist.

  • Wie behebe ich diesen Fehler?
  • Warum tritt dieser Fehler auf?
  • Was ist der Unterschied zwischen einer bedingten Anweisung und einem bedingten Block?

Antwort

In einem if Anweisung, Sie haben eine else. Wenn if nicht übereinstimmt, wird der Zweig else ausgeführt.

In einer bedingten Anweisung sind beide Aktionen ausgeführt, unabhängig davon, ob die Bedingung wahr oder falsch ist.

Eine einfache Lösung:

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

Und Sie können es präziser gestalten:

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

Wenn die Bedingung erfüllt ist 1 und keine Aktion ausgeführt wird, awk ist print. print ohne Argument gibt standardmäßig $0 aus.

Kommentare

  • Sie können es auch in awk '$2!=1?$2=0:"";1' file spielen.
  • @ terdon: Gutes Golfen. Ich denke, es kann schwierig sein, das zu verstehen.
  • @cuonglm Könnten Sie bitte die Rolle von next erklären. Ich denke, es unterdrückt der zweite Ausdruck, wenn der erste wahr ist. So etwas wie continue in C.
  • @Alexander Cska: next unterdrückt die Verarbeitung der aktuellen Eingabezeile, fahren Sie mit der nächsten fort. Dieselbe Rolle wie while, jedoch für das gesamte awk -Programm. Außerdem hat awk eine eigene while

Antwort

Der zweite Block in

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

ist nicht bedingt. Er wird für jede Zeile bearbeitet und druckt somit jeden Zeile.

Schreiben Sie stattdessen:

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

Oder schreiben Sie:

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

Dies führt dazu, dass der unbedingte Block übersprungen wird, wenn der bedingte Block übereinstimmt.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.