根据指定空参数的方式,Awk 会做出不同的响应

根据指定空参数的方式,Awk 会做出不同的响应

我似乎偶然发现了一些东西,可能是 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 的空参数,我已经这样做了,但这让我对原因感到好奇。

編輯

根据下面的评论,我理解awkawk ''不同之处在于第二次调用意味着 awk 将参数的数量视为 1(参数为空字符串)而不是 0。

我仍然不明白的是 awk 表达式中的空字符串有什么作用。

例如以下工作正常

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

答案1

这里有两个独立的事情:错误消息(实际上来自 python,而不是 awk)和 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,则不会出现错误,因为 sleep 直到 python 完成写入后才会关闭管道末端。您的结果可能会有所不同,具体取决于所涉及的确切时间。

现在,对于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 个参数,但您希望第二个参数为空,则您不能简单地省略它 - shell 不知道有一个参数被省略,因此它会将 2 个参数传递给程序,程序将出现错误。

相关内容