防止 grep 导致“bash -e”脚本过早终止

防止 grep 导致“bash -e”脚本过早终止

该脚本不输出after

#!/bin/bash -e

echo "before"

echo "anything" | grep e # it would if I searched for 'y' instead

echo "after"
exit

我可以通过删除-eshebang 行上的选项来解决这个问题,但我希望保留它,以便我的脚本在出现错误时停止。我不认为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
...

相关内容