该脚本不输出after
:
#!/bin/bash -e
echo "before"
echo "anything" | grep e # it would if I searched for 'y' instead
echo "after"
exit
我可以通过删除-e
shebang 行上的选项来解决这个问题,但我希望保留它,以便我的脚本在出现错误时停止。我不认为grep
找不到匹配项是一个错误。我怎样才能防止它突然退出?
答案1
echo "anything" | { grep e || true; }
解释:
- 这会抛出一个错误
$ echo "anything" | grep e $ echo $? 1
- 这不会引发错误
$ echo "anything" | { grep e || true; } $ echo $? 0
- DopeGhoti 的“无操作”版本(如果
true
不是内置进程,则可能避免生成进程),这不会引发错误$ echo "anything" | { grep e || :; } $ echo $? 0
意思||
是“或”。如果命令的第一部分“失败”(意味着grep e
返回非零退出代码),则||
执行后的部分将成功并返回零作为退出代码(true
始终返回零)。
答案2
一种安全、可靠的方法可选地 grep
消息:
echo something | grep e || [[ $? == 1 ]] ## print 'something', $? is 0
echo something | grep x || [[ $? == 1 ]] ## no output, $? is 0
echo something | grep --wrong-arg e || [[ $? == 1 ]] ## stderr output, $? is 1
根据POSIX手册,退出代码:
1
表示没有选择任何行。> 1
意味着错误。
答案3
如果您使用 grepset -euo pipefail
且不想在未找到记录时退出(退出代码 = 1),但仍希望它在另一个退出代码时失败,您可以使用以下命令:
#!/bin/bash
set -euo pipefail
echo "anything" | { grep e || test $? = 1; } | { grep e2 || test $? = 1; }
管道内的 grep 将仅忽略退出状态 = 1。这样您就不需要失去使用set -euo pipefail
.
在这个例子中,我故意包含了两个管道 grep,它们可能无法说明这个概念。
参考myrdd的帖子那里。
答案4
另外一个选择:
...
set +e
echo "anything" | grep e
set -e
...