awk condition de vrai et de faux

9

Je suis tombé sur le fait que si nous utilisons awk 0 inputfile, cela n'imprimera rien car cela 0signifie que la condition est fausse.

Si nous l'utilisons awk 1 inputfile, il affichera tout comme étant 1vrai pour chaque ligne interprétée par awk.

Si nous utilisons awk any_string inputfile, il n'imprimera rien car toutes les variables awk initialisées à zéro sont donc fausses.

Mais si nous utilisons awk any_integer inputfile, cela deviendra vrai et imprimera chaque ligne du fichier, puis-je savoir quelle est la raison?

Je ne trouve pas que cela ait été expliqué dans le manuel GNUawk .

sylye
la source
3
par any_integerje suppose que vous littéral comme moyen 7, 89etc .. si oui, la raison est tout autre numéro que 0moyen trueétat
Sundeep

Réponses:

13

Vrai pour awk est une chaîne non vide ou un nombre non nul (les nombres étant des nombres décimaux entiers ou à virgule flottante et avec certaines implémentations awk hexadécimales ou octales sont également pris en charge). Les choses entre guillemets doubles sont des chaînes, les nombres littéraux sans guillemets sont des nombres, mais pour toute autre chose, il existe des règles complexes pour déterminer si quelque chose doit être traité comme une chaîne ou un nombre. Le awkmanuel GNU contient un chapitre entier à ce sujet .

Vrai:

  • awk '1' (nombre différent de zéro)
  • awk '1e8' (nombre différent de zéro)
  • awk '-0.01' (nombre différent de zéro)
  • awk '"foo"' (chaîne non vide)
  • awk '"0"' (chaîne non vide)
  • awk '0 ""' (la concaténation donne une chaîne qui ici n'est pas vide)
  • echo 0 | awk '$1 ""' (idem pour un champ $ n)
  • awk 'substr("000", 1, 1)'(le résultat de substr()est toujours une chaîne)
  • echo '0foo' | awk '$0' ($ 0 est une chaîne non numérique et est donc considéré comme une chaîne (non vide))

Faux:

  • awk '0' (0 numéro)
  • awk '""' (chaîne vide)
  • echo 0000e123 | awk '$1' ($ 1 est considéré comme un nombre s'il s'agit d'une chaîne numérique qui se trouve ici et vaut 0)
  • echo ' 0 ' | awk '$0' (les espaces de début et de fin sont ignorés pour déterminer si une chaîne est numérique).
  • awk '" 2foo" - 2' (une chaîne impliquée dans une expression arithmétique est convertie en un nombre avec tout ce qui dépasse le nombre ignoré)
  • awk 'unset_or_empty_variable' (chaîne vide)
  • awk '"non-numerical-string" + 0'

YMMV:

  • awk '1e-500' (certains se plaindront, certains le traiteront comme 0)
  • awk '"0x1" + 0'(toutes les implémentations awk ne prennent pas en charge les hexadécimaux, sur ceux qui le font "0x1"est converti en 1, dans d'autres en 0. Certaines versions de la spécification POSIX exigeaient par inadvertance des implémentations pour prendre en charge ce nombre hexadécimal là-bas et il a été rétracté plus tard. gawkReconnaît toujours ce nombre hexadécimal quand POSIXLY_CORRECTest dans l'environnement)
  • awk '010 - 8' (identique (enfin pas tout à fait car le 010 est ici littéral par opposition à converti à partir d'une chaîne) pour les octaux)
  • awk '0x1 - 1'(sur les awkimplémentations qui ne prennent pas en charge les nombres hexadécimaux, 0x1est la concaténation de 0et la x1variable qui donne "0"qui est convertie en nombre (0), si vous soustrayez, 1vous obtenez -1ce qui est un nombre non nul).

Cela signifie que si vous souhaitez vérifier si une chaîne n'est pas vide, vous ne devez pas:

awk '$ 1 {print $ 1, "n'est pas vide"}'

Mais

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

Sinon, il ne dirait pas 0ou -0000E+00001234n'est pas vide.

Stéphane Chazelas
la source
Réponse impressionnante et détaillée! Une question cependant: dans le dernier exemple que vous avez donné, j'ai essayé la syntaxe et la première fonctionne, où elle saute le $ 1 qui est vide et n'imprime que la ligne avec $ 1 non vide, car si $ 1 est une chaîne vide, ce sera Faux, et donc ne pas imprimer la sortie, n'est-ce pas?
sylye