Awk reagiert unterschiedlich, je nachdem, wie ein leeres Argument angegeben wird

Awk reagiert unterschiedlich, je nachdem, wie ein leeres Argument angegeben wird

Ich bin wohl auf etwas gestoßen, bei dem es sich wahrscheinlich um einen Fehler in awk handelt, es könnte aber auch an einem Fehler in meinem Verständnis von bash/awk liegen.

Ich habe versucht, Probleme zu debuggen, bei denen die Ausgabe eines Python-Programms an awk weitergeleitet wurde, und ich erhielt die folgende Ausnahme, unabhängig davon, was der awk-Befehl tat.

close failed in file object destructor:
Error in sys.excepthook:

Original exception was:

Wie sich herausstellte, wurde awk ein leeres erstes Argument übergeben, gefolgt von -f awkfilename.awk. Der Fehler kann also mit der folgenden Befehlszeile reproduziert werden:

python -c 'print "hello"'  | awk '' 

Wenn ich jedoch awk ohne Argumente ausführe (was ich oben als gleichwertig betrachten würde), erhalte ich die awk-Hilfe, gefolgt von derselben Ausnahme

 python -c 'print "hh"'  | awk 

Usage: awk [POSIX or GNU style options] -f progfile [--] file ...
Usage: awk [POSIX or GNU style options] [--] 'program' file ...
POSIX options:      GNU long options:
    -f progfile     --file=progfile
    -F fs           --field-separator=fs
    -v var=val      --assign=var=val
    -m[fr] val
    -W compat       --compat
    -W copyleft     --copyleft
    -W copyright        --copyright
    -W dump-variables[=file]    --dump-variables[=file]
    -W exec=file        --exec=file
    -W gen-po       --gen-po
    -W help         --help
    -W lint[=fatal]     --lint[=fatal]
    -W lint-old     --lint-old
    -W non-decimal-data --non-decimal-data
    -W profile[=file]   --profile[=file]
    -W posix        --posix
    -W re-interval      --re-interval
    -W source=program-text  --source=program-text
    -W traditional      --traditional
    -W usage        --usage
    -W use-lc-numeric   --use-lc-numeric
    -W version      --version

To report bugs, see node `Bugs' in `gawk.info', which is
section `Reporting Problems and Bugs' in the printed version.

gawk is a pattern scanning and processing language.
By default it reads standard input and writes standard output.

Examples:
    gawk '{ sum += $1 }; END { print sum }' file
    gawk -F: '{ print $1 }' /etc/passwd
close failed in file object destructor:
Error in sys.excepthook:

Original exception was:

Notiz:die Meldung nach „Ursprüngliche Ausnahme war:“ ist tatsächlich leer, das habe ich nicht übersprungen.

Details zu meinem System

Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41) 
[GCC 4.4.3] on linux2

$ awk --version
GNU Awk 3.1.6

$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=10.04
DISTRIB_CODENAME=lucid
DISTRIB_DESCRIPTION="Ubuntu 10.04.3 LTS

$ uname -a
Linux <hostname> 2.6.32-37-generic #81-Ubuntu SMP Fri Dec 2 20:32:42 UTC 2011 x86_64     GNU/Linux

Ich würde mich freuen, wenn mir jemand einen Einblick geben könnte. Natürlich besteht die unmittelbare Lösung darin, das Argument zu bereinigen, das als leer an awk übergeben wird, was ich getan habe, aber das hat mich neugierig auf die Ursache gemacht.

Bearbeitungen

Aufgrund der Kommentare weiter unten verstehe ich das awkund awk ''der Unterschied besteht darin, dass der zweite Aufruf bedeutet, dass awk die Anzahl der Argumente als 1 (wobei das Argument eine leere Zeichenfolge ist) statt als 0 erkennt.

Was ich immer noch nicht verstehe, ist, was die leere Zeichenfolge als Awk-Ausdruck macht.

Zum Beispiel funktioniert das Folgende gut

$ echo "" > /tmp/empty.awk
$ python -c 'print "hello"' | awk -f /tmp/empty.awk
$ echo $?
$ 0

Antwort1

Hier passieren zwei verschiedene Dinge: die Fehlermeldungen (die eigentlich von Python und nicht von awk stammen) und die Nutzungsmeldung von awk. Um sie zu isolieren, leiten Sie einfach stderr von beiden Befehlen um:

$ python -c 'print "hello"' 2>pyerr | awk 2>awkerr
$ cat pyerr 
close failed in file object destructor:
Error in sys.excepthook:

Original exception was:
$ cat awkerr 
usage: awk [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]

AIUI Python erhält einen Fehler, weil das Programm, an das seine Ausgabe weitergeleitet wird, beendet wird (und die Pipe schließt), bevor Python dort schreibt. Hier ist ein Beispiel, das sleep 0als Programm verwendet wird, das überhaupt nichts tut und daher sehr schnell beendet wird:

$ python -c 'print "hello"' | sleep 0
close failed in file object destructor:
Error in sys.excepthook:

Original exception was:

Wenn ich jedoch verwende sleep 1, tritt kein Fehler auf, da sleep sein Ende der Pipe erst schließt, nachdem Python mit dem Schreiben fertig ist. Ihre Ergebnisse können je nach den genauen Zeitabläufen abweichen.

Nun zum awkFehler. Der Unterschied besteht darin, dass awkohne Argument nicht gültig ist, weil Siemussein Programm bereitstellen; da Sie es nicht richtig ausgeführt haben, versucht es hilfreich zu sein, indem es eine Verwendungsmeldung ausgibt, die Ihnen mitteilt, wie es ausgeführt werden soll. Andererseits awk ''weist es awk tatsächlich an, ein leeres Skript ('') auszuführen, was vollkommen gültig ist (wenn auch nicht besonders nützlich), sodass keine Verwendungsmeldung ausgegeben wird:

$ awk
usage: awk [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]
$ awk ''

Antwort2

Das Aufrufen eines Programms mit null Argumenten (oder Parametern) unterscheidet sich vom Aufrufen eines Programms mit einem leeren Argument (oder Parameter).

Um etwas C-Code als Beispiel zu verwenden:

#include <stdio.h>
int main(int argc, char** argv)
{
    printf("%d\n", argc); // print the number of arguments we've received
    return 0; // exit successfully
}

Wenn Sie dieses Programm als ausführen, examplewird 1- ausgegeben, da der Programmname immer automatisch übergeben wird und keine zusätzlichen Argumente vorhanden sind. Wenn Sie das Programm als example ''oder ausführen, example SomethingGoesHerewird ausgegeben 2, da der Programmname und entweder ein leerer Parameter oder vorhanden sind SomethingGoesHere.

Da awk mindestens zwei Parameter erwartet (seinen Namen und etwas anderes), führt der alleinige Aufruf von awk ohne Argumente zu dem, was Sie oben sehen – die Hilfe wird gedruckt.

Aus diesem Grund können Sie Argumente richtig ausrichten. Wenn Sie ein Programm hätten, das immer 3 Argumente erfordert, aber das zweite leer lassen möchten, könnten Sie es nicht einfach weglassen – die Shell wüsste nicht, dass ein Argument weggelassen wurde, und würde die 2 Argumente an das Programm weitergeben, und das Programm würde einen Fehler aufweisen.

verwandte Informationen