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

говорит

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

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

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

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

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

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

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

2 ответа2

4

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

$ 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 после определения функции.

1

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

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

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