在 POSIX shell 语法中,函数定义如何成为管道序列的一部分?

在 POSIX shell 语法中,函数定义如何成为管道序列的一部分?

POSIX shell 语法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出现的位置,那么是的,我们正在使语法变得有点复杂。

但其回报更为重要:这种 shell 的实现更加容易。

因为如果你允许在管道中定义函数,你就必须处理诸如函数的作用域是什么、它在什么环境中运行等问题。我认为标准中根本没有回答这些问题。

更糟糕的是:语法稍微复杂一点,还是实施者的工作量和复杂性增加很多。如果是前者,那么这不就是“本末倒置”的例子吗?

答案1

事实上更轻松实施者不必担心这一点。执行管道时,每个组件都在其自己的子 shell 中运行(除了 bash 中的第一个,或者如果命令是本机命令,则在 ksh88/ksh93 中的最后一个)。因此,管道中间的函数定义将为管道该组件的 shell 实例定义,但在外部不可见……这一切都是基于管道语义自动完成的。

如果您想要阻止cd管道内的函数定义(或别名定义,或诸如...之类的愚蠢命令),那么您就使实现变得复杂了:-)

答案2

为什么不可能?这毫无意义吗?当然。但它确实有效:

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

相似地:

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

定义函数和其他命令一样,都是“命令”。不过,它没有任何输出,也不接受任何输入。你甚至可以进行变量赋值。当然,这又毫无意义,但不是错误。

“为什么”可能是:KISS。你不会想用不必要的复杂性来污染你的语法。

更新:经过进一步检查,我发现 Bash 甚至懒得在函数定义之后运行管道命令。

相关内容