bash shell命令行的参数-e是什么意思?


76

我有带标题的bash shell脚本#!/bin/bash -e

当我运行脚本时,它将在grep命令运行后被中断,但是当我删除参数时-e,脚本可以正常运行。参数的含义是-e什么?


1
@MitchWheat但是bash没有-e选择,因此在这种情况下到底发生了什么?:(

2
这的确不是很明显,但有一个-e对于bash选项:serverfault.com/questions/391255/...
Eric O Lebigot

只有一点。例如,当您找到以下内容时:[-e filepath]如果文件存在,则返回true。
Alberto Perez

Answers:


105

-e选项的意思是“如果任何管道以非零('错误')退出状态结束,请立即终止脚本”。因为grep返回的退出状态是1找不到任何匹配项,所以-e即使没有真正的“错误” ,它也可能导致脚本终止。

如果您想保留该-e选项,但又有一条grep命令可能找不到有效的匹配项,则可以|| :在该grep命令后追加。这意味着“或者,如果grep命令返回的退出状态为非零,则运行:(不执行任何操作)”;因此,最终效果是禁用-egrep命令。所以:

grep PATTERN FILE... || :

编辑补充:上述方法丢弃每一个错误:如果grep回报率1,因为它没有找到任何匹配,这是忽略不计,而且如果grep回报率2,因为有一个错误,就是忽视了,如果grep不在路径(所以猛砸回报127),这是被忽略-依此类推。因此,与其相比:,最好使用命令检查结果代码并重新发出错误(如果不是)的命令1。例如:

grep PATTERN FILE || (( $? == 1 ))

但这破坏了出口状态。通常,当失败的命令使用终止Bash脚本时-e,该脚本将返回命令的退出状态,但是在上面的示例中,脚本将仅返回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,而不是无限递归)。


非常好。我已经习惯于使用您的建议来捕获退出代码以供以后使用:grep XXX FILE || exitcode=$?。超级好用!
dsummersl

@dsummersl:太好了,很高兴您喜欢它!您的评论鼓励我通过一些可能需要的改进来扩大答案。
ruakh

真的,谢谢你。您概述的模式很有启发性;这是一个很好的模式,可以防止意外的退出代码,同时忽略预期的退出代码...我绝对可以看到使用这种模式来简化脚本的主要流程。
dsummersl

@ruakh很好的答案,grep函数确实很有用。谢谢。

只有一点。例如,当您找到以下内容时:[-e filepath]如果文件存在,则返回true。
艾伯托·佩雷斯

18

精美的手册中

除了单字符外壳程序命令行选项(请参阅内置集合)之外,还可以使用多个多字符选项。

然后,如果我们看看该set说些什么:

-e
如果管道(请参阅管道)可能由单个简单命令(请参见简单命令),括号中包含的subshel​​l命令(请参见命令分组)或作为命令列表中一部分而执行的命令之一组成,则立即退出花括号(请参阅命令分组)返回非零状态。

因此,当您说时bash -e,如果脚本中的任何命令失败(即返回存在非零的存在状态),则整个脚本将立即失败。因此,您grep将返回一个非零值,因为它不匹配,并且如果您-e在运行bash时指定,则会关闭整个脚本。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.