awk Zustand von wahr und falsch

9

Ich bin darauf gestoßen, dass wenn wir verwenden awk 0 inputfile, es nichts drucken wird, was 0bedeutet, dass der Zustand falsch ist.

Wenn wir verwenden awk 1 inputfile, wird alles als 1wahr für jede Zeile gedruckt , die awk interpretiert.

Wenn wir verwenden awk any_string inputfile, wird nichts gedruckt, da alle awk-Variablen als Null initialisiert und somit falsch sind.

Aber wenn wir verwenden awk any_integer inputfile, wird es wahr und druckt jede Zeile der Datei. Darf ich wissen, was der Grund ist?

Ich kann nicht finden, dass dies im GNU- awkHandbuch erklärt wurde .

Sylye
quelle
3
von any_integerich Ihnen mittlere Zahl kommen wie annehmen 7, 89etc .. wenn ja, ist Grund jede andere Zahl als 0Mittel trueZustand
Sundeep

Antworten:

13

True für awk ist entweder eine nicht leere Zeichenfolge oder eine Zahl ungleich Null (wobei Zahlen eine Dezimalzahl oder ein Gleitkomma sind und bei einigen awk-Implementierungen auch hexadezimal oder oktal unterstützt werden). In doppelte Anführungszeichen eingeschlossene Dinge sind Zeichenfolgen, nicht zitierte Literalzahlen sind Zahlen, aber für alles andere gibt es komplexe Regeln, um zu bestimmen, ob etwas als Zeichenfolge oder als Zahl behandelt werden soll. Das GNU- awkHandbuch enthält dazu ein ganzes Kapitel .

Wahr:

  • awk '1' (Zahl ungleich Null)
  • awk '1e8' (Zahl ungleich Null)
  • awk '-0.01' (Zahl ungleich Null)
  • awk '"foo"' (nicht leere Zeichenfolge)
  • awk '"0"' (nicht leere Zeichenfolge)
  • awk '0 ""' (Verkettung ergibt eine Zeichenfolge, die hier nicht leer ist)
  • echo 0 | awk '$1 ""' (Gleiches gilt für ein $ n-Feld)
  • awk 'substr("000", 1, 1)'(Ergebnis von substr()ist immer eine Zeichenfolge)
  • echo '0foo' | awk '$0' ($ 0 ist eine nicht numerische Zeichenfolge und wird daher als Zeichenfolge (nicht leer) betrachtet.)

Falsch:

  • awk '0' (0 Nummer)
  • awk '""' (leerer String)
  • echo 0000e123 | awk '$1' ($ 1 wird als Zahl betrachtet, wenn es sich um eine numerische Zeichenfolge handelt, die hier steht und 0 ist.)
  • echo ' 0 ' | awk '$0' (führende und nachfolgende Leerzeichen werden ignoriert, um festzustellen, ob eine Zeichenfolge numerisch ist).
  • awk '" 2foo" - 2' (Eine Zeichenfolge, die an einem arithmetischen Ausdruck beteiligt ist, wird in eine Zahl konvertiert, bei der alles über die Zahl hinaus ignoriert wird.)
  • awk 'unset_or_empty_variable' (leerer String)
  • awk '"non-numerical-string" + 0'

YMMV:

  • awk '1e-500' (Einige werden sich beschweren, andere werden es als 0 behandeln)
  • awk '"0x1" + 0'(Nicht alle awk-Implementierungen unterstützen Hexadezimalzahlen, bei denen, die dies tun , wird in andere "0x1"konvertiert . Einige Versionen der POSIX-Spezifikation erforderten versehentlich Implementierungen, um diese Hex-Nummer dort zu unterstützen, und sie wurde später zurückgezogen. Erkennt diese Hex-Nummer immer noch, wenn sie aktiviert ist die Umgebung)10gawkPOSIXLY_CORRECT
  • awk '010 - 8' (Gleiches (auch nicht ganz, da die 010 hier wörtlich ist und nicht aus einer Zeichenfolge konvertiert) für Oktale)
  • awk '0x1 - 1'(Bei awkImplementierungen, die keine Hex-Zahlen unterstützen, 0x1ist die Verkettung von 0und die x1Variable, die ergibt, "0"die in eine Zahl (0) konvertiert wird. Wenn Sie subtrahieren, erhalten 1Sie eine Zahl -1ungleich Null.)

Dies bedeutet, dass Sie Folgendes nicht tun sollten, wenn Sie überprüfen möchten, ob eine Zeichenfolge nicht leer ist:

awk '$ 1 {print $ 1, "ist nicht leer"}'

Aber

awk '$1 != "" {print $1, "is not empty"}'

Sonst würde es nicht sagen 0oder -0000E+00001234sind nicht leer.

Stéphane Chazelas
quelle
Beeindruckende und detaillierte Antwort! Eine Frage: Beim letzten Beispiel, das Sie gegeben haben, habe ich die Syntax ausprobiert und die erste funktioniert, bei der die leere $ 1 übersprungen wird und nur die Zeile mit $ 1 gedruckt wird, die nicht leer ist. Wenn $ 1 eine leere Zeichenfolge ist, ist dies der Fall Falsch und damit die Ausgabe nicht drucken, nicht wahr?
Sylye