我有标题为#!/bin/bash -e
的bash shell脚本。
当我运行脚本时,它将在grep
命令运行后被中断,但是当我删除参数-e
时,脚本可以正常运行。参数-e
是什么意思?
答案 0 :(得分:82)
-e
选项意味着“如果任何管道以非零('错误')退出状态结束,则立即终止脚本”。由于grep
在找不到任何匹配项时返回退出状态1
,因此即使没有真正的“错误”,也可能导致-e
终止脚本。< / p>
如果要保留-e
选项,但也有grep
命令可能有效地找不到匹配项,则可以将|| :
附加到grep
命令。这意味着“或者,如果grep
命令返回非零退出状态,则运行:
(不执行任何操作)”;所以净效果是禁用-e
命令的grep
。所以:
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
,而不是无限地递归)。
答案 1 :(得分:13)
来自fine manual:
除了单字符shell命令行选项(请参阅Set Builtin)之外,您还可以使用多个多字符选项。
然后,如果我们看一下set
要说的话:
-e
如果管道(请参阅管道)可能包含一个简单命令(请参阅简单命令),括在括号中的子shell命令(请参阅命令分组),或作为命令列表的一部分执行的命令之一,则立即退出大括号(请参阅命令分组)返回非零状态。
因此,当您说bash -e
时,如果脚本中的任何命令失败(即返回非零存在状态),则整个脚本会立即失败。因此,grep
返回非零值,因为它不匹配,并且如果在运行bash时指定-e
,则会关闭整个脚本。