简短答案
写
ps -ef | grep bar | { grep -v grep || test $? = 1; }
如果您正在使用set -e
。
如果使用bash的pipefail
选项(set -o pipefail
),请记住将异常处理(||test
)应用于grep
管道中的每个对象:
ps -ef | { grep bar || test $? = 1; } | { grep -v grep || test $? = 1; }
在外壳程序脚本中,我建议您使用“ catch-1-grep”(c1grep)实用程序功能:
c1grep() { grep "$@" || test $? = 1; }
解释
grep
的退出状态为0、1或2:[1]
0
表示选择了一条线
1
表示未选择任何行
2
表示发生错误
grep
如果被信号中断(例如130
SIGINT),它也可以返回其他代码。
由于我们只想忽略退出状态1
,因此我们使用test
了抑制特定退出状态的功能。
- 如果
grep
返回0
,test
则不运行。
- 如果
grep
返回1
,test
则运行并返回0
。
- 如果
grep
返回任何其他值,test
则运行并返回1
。
在最后一种情况下,脚本将由于set -e
或立即退出set -o pipefail
。但是,如果您根本不关心grep
错误,那么您当然可以编写
ps -ef | grep bar | { grep -v grep || true; }
正如肖恩建议的。
Shell脚本中的[additional]用法
在shell脚本中,如果您使用grep
很多,建议您定义一个实用程序函数:
c1grep() { grep "$@" || test $? = 1; }
这样,您的管道将再次变得简短而简单,而不会丢失set -e
and的功能set -o pipefail
:
ps -ef | c1grep bar | c1grep -v grep
仅供参考:
- 我称其
c1grep
为强调仅是捕获退出状态1
,仅此而已。
- 我本可以调用函数
grep
(grep() { env grep "$@" ...; }
),但我更喜欢使用一个不太混乱和更明确的名称c1grep
。
[其他] ps
+grep
所以,如果你想知道如何避免grep -v grep
甚至| grep
部分ps|grep
可言,看看一些其他的答案; 但这有点离题了。
[1]grep
联机帮助页
set -e
不是bash特定的,而是适用于任何POSIX兼容的外壳(sh
等)