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

432
user322908

Грамматика оболочки 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появляется, то да, мы усложняя немного грамматику.

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

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

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

0
Кажется, он работает в bash, хотя ничего не делает: `ls | f () `. choroba 8 лет назад 1

2 ответа на вопрос

4
Daniel B

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

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

Я думаю, что я не объяснил себя полностью в первоначальном вопросе. Я отредактировал вопрос, чтобы сделать его ближе к делу. Ваш ответ поучителен, спасибо, но, пожалуйста, посмотрите на мои изменения. user322908 8 лет назад 0
Вы говорите, что реализация намного проще, но так ли это? Имея меньше особых случаев, вам нужно меньше кода. Меньшее количество кода означает меньше головной боли, а также меньше ошибок. Функции в Bash также не имеют области видимости. Это не объектно-ориентированный. Там только "окружение". Конечно, во время выполнения функции. Daniel B 8 лет назад 0
1
Stephen Harris

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

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

Команды конвейера не выполняются в подоболочках, по крайней мере, в Bash. Они являются прямыми дочерними процессами оболочки. Daniel B 8 лет назад 0
Баш вилки; дочерний процесс - еще один экземпляр этой оболочки bash; переменные и другие изменения (функции, изменения каталогов и т. д.), установленные в этой оболочке, не передаются обратно родителю. С точки зрения этого вопроса, это можно рассматривать, как если бы это была недоработка. FWIW на странице руководства написано `Каждая команда в конвейере выполняется как отдельный процесс (т. Е. В подоболочке) .` :-) Stephen Harris 8 лет назад 1
Только встроенные функции Bash (например, определения функций) будут выполняться в подоболочке (ну, может быть). Все остальное уже отдельный процесс. Daniel B 8 лет назад 0
@DanielB мой вопрос был действительно о стандарте POSIX ... где он комментирует в стандарте, выполняется ли термин конвейера в отдельном процессе, подоболочке или как-то еще? user322908 8 лет назад 0
@ user322908 http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_01_01 Daniel B 8 лет назад 0
@DanielB Мне жаль, что я испытываю такую ​​боль ... но я все еще не вижу, выполняются ли термины в конвейере в отдельном процессе / подоболочке, по ссылке, которую вы разместили. user322908 8 лет назад 0
Раздел 2.12 «Кроме того, каждая команда многокомпонентного конвейера находится в среде подоболочек» Stephen Harris 8 лет назад 1

Похожие вопросы