Как определение функции может быть частью конвейерной последовательности в грамматике оболочки POSIX?

Грамматика оболочки POSIX по адресу http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html

говорит

pipe_sequence    :                             command
                 | pipe_sequence '|' linebreak command
                 ;
command          : simple_command
                 | compound_command
                 | compound_command redirect_list
                 | function_definition

Это означает, что определение функции может быть термином в последовательности каналов. Как это возможно? Определение функции не может иметь стандартный ввод или вывод, и это не команда, которая может быть выполнена. Только вызов функции, который является простой командой, может быть выполнен.

Добавлено после первого комментария и ответа:

Если мы откололись function_definition от command здесь, и добавить его в качестве еще одной альтернативы, где еще command появляется, тогда да, мы немного усложняем грамматику.

Но окупаемость гораздо важнее: реализация такой оболочки намного проще.

Потому что, если вы разрешаете определения функций в конвейере, вам приходится иметь дело с такими вопросами, как область действия функции и в какой среде она выполняется. Я не верю, что на такие вопросы вообще отвечают стандарт.

Что еще хуже: немного больше сложности в грамматике или гораздо больше работы и сложности для разработчика. Если первое, то разве это не случай "хвоста, виляющего собакой"?

2 ответа

Решение

Реализатору на самом деле легче не беспокоиться об этом. При выполнении канала каждый компонент запускается в своей собственной подоболочке (за исключением, может быть, первого в bash или последнего в ksh88/ksh93, если команда является нативной). Таким образом, определение функции в середине конвейера должно быть определено для экземпляра оболочки для этого компонента конвейера, но не видно снаружи... и все это автоматически на основе семантики конвейеров.

Если вы хотите запретить определения функций (или определения псевдонимов, или глупые команды, такие как cd...) внутри конвейера, тогда вы усложнили реализацию:-)

Почему это не возможно? Это бессмысленно? Определенно. Но это работает:

$ function asdf { echo "bla"; } | hexdump -C; echo EOF
EOF

Так же:

$ function asdf { echo "bla"; } | asdf | hexdump -C; echo EOF
-bash: asdf: command not found
EOF

Определение функции - это "команда", как и любая другая. Это не имеет никакого выхода и не принимает никакого ввода, все же. Вы могли бы даже сделать присвоение переменной. Опять бессмысленно, конечно, но не ошибка.

"Почему", вероятно, это: ПОЦЕЛУЙ. Вы не хотели бы загрязнять свою грамматику ненужной сложностью.

Обновление: После дальнейшего изучения я обнаружил, что Bash даже не потрудился запустить команды pipe после определения функции.

Другие вопросы по тегам