아마도 awk의 버그일 수도 있지만 bash/awk에 대한 이해의 버그일 수도 있습니다.
Python 프로그램의 출력이 awk로 파이프되는 문제를 디버깅하려고 했는데 awk 명령이 수행하는 작업에 관계없이 다음 예외가 발생했습니다.
close failed in file object destructor:
Error in sys.excepthook:
Original exception was:
결과적으로 awk는 빈 첫 번째 인수를 전달한 다음 -f awkfilename.awk
. 따라서 다음 명령줄을 사용하여 오류를 재현할 수 있습니다.
python -c 'print "hello"' | awk ''
그러나 인수 없이 awk를 실행하면(위에서 동등한 것으로 간주하는 것임) awk 도움말과 동일한 예외가 발생합니다.
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:
메모:"원래 예외는 다음과 같습니다:" 이후의 메시지는 실제로 비어 있으며 건너뛴 것이 아닙니다.
내 시스템에 대한 세부정보
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
누군가가 통찰력을 제공할 수 있다면 기쁠 것입니다. 물론 즉각적인 해결책은 awk에 비어 있는 것으로 전달되는 인수를 정리하는 것인데, 이로 인해 원인이 궁금했습니다.
편집
아래 설명에 따르면 두 번째 호출은 awk가 인수 수를 0 대신 1(인수는 빈 문자열임)로 본다는 점에서 다릅니다 awk
.awk ''
내가 아직도 이해하지 못하는 것은 awk 표현처럼 빈 문자열이 하는 일이 무엇인지입니다.
예를 들어 다음은 잘 작동합니다
$ echo "" > /tmp/empty.awk
$ python -c 'print "hello"' | awk -f /tmp/empty.awk
$ echo $?
$ 0
답변1
여기에는 두 가지 별도의 작업이 진행됩니다. 오류 메시지(실제로 awk가 아닌 Python에서 온 메시지)와 awk의 사용 메시지입니다. 이를 격리하려면 두 명령 모두에서 stderr을 리디렉션하면 됩니다.
$ 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에 오류가 발생하는 이유는 Python이 쓰기 전에 프로그램의 출력이 파이프로 연결되어 종료(& 파이프를 닫음)되기 때문입니다. 다음은 sleep 0
아무것도 하지 않고 매우 빠르게 종료되는 프로그램을 사용하는 예입니다 .
$ python -c 'print "hello"' | sleep 0
close failed in file object destructor:
Error in sys.excepthook:
Original exception was:
하지만 을 사용하면 sleep 1
python이 쓰기를 완료할 때까지 sleep이 파이프 끝을 닫지 않기 때문에 오류가 없습니다. 관련된 정확한 타이밍에 따라 결과가 다를 수 있습니다.
이제 awk
오류가 발생했습니다. 차이점은 awk
인수가 없으면 유효하지 않다는 것입니다.~ 해야 하다프로그램을 제공하고; 부적절하게 실행했기 때문에 실행 방법을 알려주는 사용법 메시지를 인쇄하여 도움을 주려고 합니다. 반면에 awk ''
실제로 awk에게 빈 스크립트('')를 실행하라고 지시하는 것입니다. 이는 완벽하게 유효하므로(매우 유용하지는 않지만) 사용법 메시지가 인쇄되지 않습니다.
$ awk
usage: awk [-F fs] [-v var=value] [-f progfile | 'prog'] [file ...]
$ awk ''
답변2
인수(또는 매개변수)가 없는 프로그램을 호출하는 것은 하나의 비어 있는 인수(또는 매개변수)를 사용하여 프로그램을 호출하는 것과 다릅니다.
일부 C 코드를 예로 사용하려면 다음을 수행하십시오.
#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
}
이 프로그램을 실행하면 example
인쇄됩니다 1
. 프로그램 이름이 항상 자동으로 전달되고 추가 인수가 없기 때문입니다. 프로그램 이름과 빈 매개변수 또는 가 있으므로 프로그램을 example ''
또는 로 실행하면 example SomethingGoesHere
가 인쇄됩니다 .2
SomethingGoesHere
awk는 최소 2개의 매개변수(이름 및 기타 항목)를 기대하므로 인수 없이 awk 자체를 호출하면 위에서 볼 수 있는 결과, 즉 도움말이 인쇄됩니다.
이러한 이유로 인수를 적절하게 정렬할 수 있습니다. 항상 3개의 인수가 필요한 프로그램이 있지만 두 번째 인수를 공백으로 두려는 경우 간단히 생략할 수 없습니다. 쉘은 생략된 인수가 있다는 것을 알지 못하므로 2개의 인수를 전달합니다. 프로그램에 오류가 발생하게 됩니다.