awk warunek prawda i fałsz

9

Natknąłem się na to, że jeśli użyjemy awk 0 inputfile, nie wydrukuje niczego, co 0oznacza fałsz warunku.

Jeśli użyjemy awk 1 inputfile, to wypisze wszystko jako 1prawdziwe dla każdej interpretacji awk linii.

Jeśli użyjemy awk any_string inputfile, nic nie wydrukuje, ponieważ wszystkie zmienne awk zostały zainicjowane jako zero, a więc fałsz.

Ale jeśli użyjemy awk any_integer inputfile, stanie się to prawdą i wydrukujemy każdą linię pliku, czy mogę wiedzieć, jaki jest powód?

Nie mogę jednak znaleźć tego wyjaśnienia w podręczniku GNUawk .

sylye
źródło
3
przez any_integerPrzypuszczam, średnią liczbę dosłownego jak 7, 89etc .. jeśli tak, to powodem jest dowolna liczba innych niż 0środki truewarunku
Sundeep

Odpowiedzi:

13

Prawda dla awk jest niepustym łańcuchem lub liczbą niezerową (z liczbami dziesiętnymi całkowitymi lub zmiennoprzecinkowymi, a także z niektórymi implementacjami awk szesnastkowymi lub ósemkowymi). W podwójnych cudzysłowach znajdują się ciągi, niecytowane liczby literalne są liczbami, ale w innych przypadkach istnieją złożone reguły określające, czy coś należy traktować jako ciąg, czy liczbę. Podręcznik GNU awkzawiera cały rozdział na ten temat .

Prawdziwe:

  • awk '1' (liczba niezerowa)
  • awk '1e8' (liczba niezerowa)
  • awk '-0.01' (liczba niezerowa)
  • awk '"foo"' (niepusty ciąg)
  • awk '"0"' (niepusty ciąg)
  • awk '0 ""' (konkatenacja daje ciąg, który tutaj nie jest pusty)
  • echo 0 | awk '$1 ""' (to samo dla pola $ n)
  • awk 'substr("000", 1, 1)'(wynikiem substr()jest zawsze ciąg znaków)
  • echo '0foo' | awk '$0' ($ 0 jest łańcuchem nienumerycznym, więc jest uważany za ciąg (niepusty))

Fałszywe:

  • awk '0' (0 liczba)
  • awk '""' (pusta struna)
  • echo 0000e123 | awk '$1' (1 $ jest uważany za liczbę, jeśli jest to ciąg liczbowy, który jest tutaj i ma wartość 0)
  • echo ' 0 ' | awk '$0' (początkowe i końcowe spacje są ignorowane, aby ustalić, czy łańcuch jest liczbowy).
  • awk '" 2foo" - 2' (ciąg biorący udział w wyrażeniu arytmetycznym jest konwertowany na liczbę z pominięciem wszystkiego, co przekracza liczbę)
  • awk 'unset_or_empty_variable' (pusta struna)
  • awk '"non-numerical-string" + 0'

YMMV:

  • awk '1e-500' (niektórzy będą narzekać, inni będą traktować to jako 0)
  • awk '"0x1" + 0'(nie wszystkie implementacje awk obsługują dane szesnastkowe, na tych, które robią, "0x1"są konwertowane na 1, w innych na 0. Niektóre wersje specyfikacji POSIX nieumyślnie wymagały implementacji do obsługi tamtej liczby szesnastkowej i zostały wycofane później. Nadal gawkrozpoznaje tę liczbę szesnastkową, gdy POSIXLY_CORRECTjest w środowisko)
  • awk '010 - 8' (to samo (no nie całkiem, ponieważ 010 jest tutaj dosłowny, w przeciwieństwie do konwersji z ciągu) dla ósemek)
  • awk '0x1 - 1'(w awkimplementacjach, które nie obsługują liczb szesnastkowych, 0x1jest konkatenacją 0i x1zmienną, która daje, "0"która jest konwertowana na liczbę (0), jeśli odejmiesz 1, otrzymasz -1liczbę niezerową).

Oznacza to, że jeśli chcesz sprawdzić, czy ciąg nie jest pusty, nie powinieneś:

awk „1 $ {drukuj 1 $,„ nie jest pusty ”}”

Ale

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

W przeciwnym razie nie powiedziałby 0lub nie byłby -0000E+00001234pusty.

Stéphane Chazelas
źródło
Imponująca i szczegółowa odpowiedź! Jedno pytanie: w ostatnim podanym przez ciebie przykładzie wypróbowałem składnię, a pierwsze działa, gdzie pomija 1 $, który jest pusty i wypisuje tylko te wiersze z 1 $ niepustym, ponieważ jeśli 1 $ jest pustym łańcuchem, to będzie Fałszywy, a zatem nie drukujący wydruków, prawda?
sylye