在管道中使用 shell 函数是否符合 POSIX 标准?

在管道中使用 shell 函数是否符合 POSIX 标准?

是否可以在管道中使用 shell 函数?

假设我有一个函数,其作用类似于grep,名为mygrep。有没有办法,只使用 POSIX shell 功能,能够 mygrep像这样调用:

if ps | mygrep foo ; then
   echo "process foo is running"
fi

或者管道仅限于外部命令?

答案1

是的。请参阅这个文件

1. 简介

POSIX.1-2017 的 Shell 和实用程序卷描述了符合 POSIX 的系统为应用程序提供的命令和实用程序。

2.9.2 管道

管道是由控制运算符“|”分隔的一个或多个命令的序列。

2.9.5 函数定义命令

函数是用户定义的名称,用作简单命令[...]

函数定义命令的格式如下:

fname ( ) compound-command [io-redirect ...]

2.9 Shell 命令

命令是下列之一:

  • 简单命令 [...]
  • [...]

因此,|命令可以分开;命令可以是简单命令;函数名称用作简单命令。你的问题的答案是:是的,这种语法

some_command | some_function

由 POSIX 定义。


尝试起来相当容易(在 Debian 9 中sh提供测试dash):

mygrep() { grep "$@"; }

if ps | mygrep foo ; then
   echo "process foo is running"
fi

if ps | mygrep ps ; then
   echo "process ps is running"
fi

(如果有的话,ps | mygrep foo也会检测一个过程foobar。我知道这个问题超出了你的问题范围,我们可以忽略它)。

在这个例子中,mygrep它很简单。它返回最后一个(也是唯一的)命令的退出状态。在构建具有更复杂逻辑的函数时,您可能需要特殊的内置函数return来返回所需的退出状态。

还要注意,输出grep不会被抑制。shell 函数不仅可以在管道中使用,其输出也可以重定向。例如:

if ps | mygrep ps >/dev/null ; then
   echo "process ps is running"
fi

答案2

您必须使用单行格式,或将表达式打包为 ${}。以您编写的 bash 脚本的形式,这是不可能的。

相关内容