是否可以在管道中使用 shell 函数?
假设我有一个函数,其作用类似于grep
,名为mygrep
。有没有办法,只使用 POSIX shell 功能,能够
mygrep
像这样调用:
if ps | mygrep foo ; then
echo "process foo is running"
fi
或者管道仅限于外部命令?
答案1
是的。请参阅这个文件。
POSIX.1-2017 的 Shell 和实用程序卷描述了符合 POSIX 的系统为应用程序提供的命令和实用程序。
从2.9.2 管道:
管道是由控制运算符“|”分隔的一个或多个命令的序列。
函数是用户定义的名称,用作简单命令[...]
函数定义命令的格式如下:
fname ( ) compound-command [io-redirect ...]
命令是下列之一:
- 简单命令 [...]
- [...]
因此,|
命令可以分开;命令可以是简单命令;函数名称用作简单命令。你的问题的答案是:是的,这种语法
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 脚本的形式,这是不可能的。