-e 选项表示“如果任何管道以非零('错误')退出状态结束,则立即终止脚本”。由于grep 在找不到任何匹配项时返回退出状态1,因此即使没有真正的“错误”,它也会导致-e 终止脚本。
如果您想保留-e 选项,但还有一个grep 命令可能有效地找不到匹配项,您可以将|| : 附加到grep 命令。这意味着“或者,如果grep 命令返回非零退出状态,则运行:(什么都不做)”;所以最终效果是为grep 命令禁用-e。所以:
grep PATTERN FILE... || :
编辑添加:上述方法丢弃所有错误:如果grep返回1,因为它没有找到匹配项,则忽略,但如果grep返回2,因为有是一个错误,它会被忽略,如果 grep 不在路径中(所以 Bash 返回 127), 会被忽略 - 依此类推。因此,与: 相比,使用检查结果代码并在不是1 时重新发出错误的命令可能会更好。例如:
grep PATTERN FILE || (( $? == 1 ))
但这会破坏退出状态;通常,当失败的命令以-e 终止 Bash 脚本时,脚本将返回命令的退出状态,但在上面的示例中,脚本只会返回 1。如果(且仅当)我们关心这一点,我们可以通过编写如下代码来修复它:
grep PATTERN FILE || exit_code=$?
if (( exit_code > 1 )) ; then
exit $exit_code
fi
(第一行 c/o dsummersl 的评论)。
此时,最好创建一个 shell 函数来为我们处理这个问题:
function grep_no_match_ok () {
local exit_code
grep "$@" || exit_code=$?
return $(( exit_code == 1 ? 0 : exit_code ))
}
(注意使用return 而不是exit;我们将让-e 在适当的时候处理退出);这样,我们就可以这样写:
grep_no_match_ok PATTERN FILE # won't kill script if no matches are found
事实上,由于我们很可能希望在此脚本中所有次出现grep 时使用此函数,因此我们实际上可以将函数命名为grep:
function grep () {
local exit_code
command grep "$@" || exit_code=$?
return $(( exit_code == 1 ? 0 : exit_code ))
}
grep PATTERN FILE # won't kill script if no matches are found
(注意使用command 绕过它自己体内的shell 函数:我们希望函数调用常规程序grep,而不是无限递归)。