使用set -e时,bash单行条件失败

时间:2012-03-27 08:41:38

标签: bash

我开始在bash脚本中使用set -e, 并发现简短形式的条件表达式会破坏脚本的执行。

例如,以下行应检查$ var是否为空:

[ -z "$var" ] && die "result is empty"

但是当$ var的长度非零时,会导致脚本无声退出。

我在很多地方使用过这种形式的条件表达式......

我该怎么做才能让它正确运行?用“if”构造重写一切(这会很难看)?或者放弃“set -e”?

编辑:每个人都在要求代码。这是完整的[非]工作示例:

#!/bin/bash
set -e

function check_me()
{
    ws="smth"
    [ -z "$ws" ] && echo " fail" && exit 1
}

echo "checking wrong thing"
check_me
echo "check finished"

我希望它能在函数调用之前和之后打印两个回声。 但是它在check_me函数中默默地失败了。输出是:

checking wrong thing

4 个答案:

答案 0 :(得分:5)

使用

[ -n "$var" ] || die "result is empty"

这样,如果$var非空,则整个语句的返回值为true,因此不会触发ERR陷阱。

答案 1 :(得分:2)

您应编写脚本,以便任何命令都不会以非零状态退出。

在你的命令中[ -z "$var" ]可以是真的,在这种情况下你可以调用die,或者假,-e就是这样。

如你所说,用if写,或者使用类似的东西:

[ -z "$var" ] && die "result is empty" || true

我建议if

答案 2 :(得分:2)

我担心你必须重写所有内容,所以不会发生虚假陈述。

set -e的定义很明确:

  

-e如果一个简单的命令(参见上面的SHELL GRAMMAR)以非零状态退出,则立即退出。如果失败的命令是紧跟在while或者直到关键字之后的命令列表的一部分,在if语句中是测试的一部分,并且&&amp ;;的一部分,则shell不会退出。或||列表,或者命令的返回值是否被反转! ERR上的陷阱(如果已设置)将在shell退出之前执行。

您正在使用Bash的“优化”系统:因为false语句会导致AND(&&)语句永远不会成立,bash知道它不必执行该行的第二部分。但是,这是对系统的巧妙“滥用”,而不是预期的行为,因此与set -e不兼容。您必须重写所有内容,以便使用正确的if s。

答案 3 :(得分:0)

bash帮助不是很清楚,只有&&||链中的 last 语句会导致{{1}下的退出}}。 set -e会在foo && bar返回false时退出,但如果bar返回false则不会退出。

所以你的脚本应该工作......但事实并非如此。为什么呢?

这不是因为foo测试失败。这是因为失败使功能 返回非零状态

-z

所以有多种方法可以解决这个问题。您可以将#!/bin/bash set -e function check_me() { ws="smth" [ -z "$ws" ] && echo " fail" && exit 1 # The line above fails, setting $? to 1 # The function now returns, returning 1! } echo "checking wrong thing" check_me # function returns 1, causing exit here echo "check finished" 添加到函数内的条件,或调用||true的行。但正如其他人所指出的,使用check_me有其自身的问题。

在这个特定的场景中,||true所需的后置条件是“这个东西是有效的还是脚本已退出”,直截了当的做法就是这样写,即check_me

但是使用[[ -n "$ws" ]] || die "whatever"条件实际上通常可以正常使用&&,只要你不使用这样的条件作为函数中的最后一件事。您需要在此类条件之后添加显式set -etrue或甚至return 0作为语句,除非您打算该函数在条件时返回false失败。