我想用set -e
保护我的大多数bash脚本,以便在脚本处理过程中检测到错误时提前和大声失败。但是,我仍然希望能够运行一些实际上预期会失败的命令,例如使用grep
来评估某些文件内容的存在/不存在,这些文件内容用于指示其余部分的控制流。脚本。如何在grep
上下文中运行set -e
,以便允许A)grep失败并且B)grep的存在状态被记录以供脚本的其余部分访问?
在普通的POSIX中,我会做类似的事情:
grep 'needle' haystack >/dev/null
if [ "$?" -eq 0 ]; then
handle_grep_results
else
handle_grep_no_results
fi
但是,在本节之前指定set -e
时,只要grep找不到针,脚本就会提前退出。解决此问题的一种方法是暂时禁用set +e
的保护,然后在该部分后重新启用它们,但如果有意义,我宁愿保留保护。这可能与bash一起使用吗?
答案 0 :(得分:1)
您只需查看grep
的返回状态:
grep -q luck myfile.txt || no_luck=1
Shell实用程序使用返回状态与shell通信;他们正在沟通的不一定是错误的条件。正如grep示例所示,它可以是一个简单的布尔值。实际上,[[
内置(及其朋友[
和test
)正是这样做的:使用状态代码返回布尔结果。这并没有使这些工具变得“松懈”。
set -e
忽略在||
或&&
连接器的条件或左侧执行的命令的非零状态返回,这使得可以使用{{ 1}}。
话虽如此,set -e
是一个非常生硬的工具,通常不建议在生产代码中使用它。您始终可以使用-e
明确失败:
||
答案 1 :(得分:1)
您的if
命令似乎包含一些拼写错误(#
之前的额外]
和遗漏空间),但更一般地说,您应该了解非常 if
的目的是运行命令并检查其退出代码。任何看起来像
command
if [ $? = 0 ]; then
更紧凑,更具惯用性
if command; then
并且在此上下文中,command
的失败退出状态不是导致set -e
终止脚本的条件(因为那时脚本中没有else
子句set -e
!)
在这个then
和else
块都包含简单命令的特定示例中,您可以简化为简写
grep -q 'needle' haystack && handle_grep_results || handle_grep_no_results
也暗示
command || true
如果您只是不关心command
在set -e
的脚本中是否成功。
(另请注意grep -q
超过grep >/dev/null
- 前者暗示-m 1
,即grep
可以关闭文件,并在找到后立即返回成功匹配。)