2

Кажется, я наткнулся на что-то, что, вероятно, является ошибкой в 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 и awk '' отличаются тем, что второй вызов означает, что awk видит количество аргументов равным 1 (с аргументом, являющимся пустой строкой) вместо 0.

Что я до сих пор не понимаю, так это то, что делает пустая строка в выражении awk.

Например, следующие хорошо работает

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

2 ответа2

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 аргумента к программе, и программа будет иметь ошибку.

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 ...]

Python AIUI получает ошибку, потому что программа выводит свои выходные данные (и закрывает канал) перед тем, как 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 ''

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .