KSH - if/then/else 与双放大器 (&&) 和双管 (||)

KSH - if/then/else 与双放大器 (&&) 和双管 (||)

我想知道关于 if/then/else 的最佳实践是什么;我倾向于使用以下形式(因为我发现它更容易阅读)

#!/usr/bin/ksh
#

[[ -f /path/to/target/file ]] && {
    echo "File exists"
} || {
    echo "No such file"
}

而不是这种形式

#!/usr/bin/ksh
#

if [ -f /path/to/target/file ] ; then
    echo "File exists"
else
    echo "No such file"
fi

我还在复杂块true之前添加了一条语句} || {,以确保“else”部分不会被执行。

您有什么建议?

答案1

这种风格的问题在于这两种形式并不等同。当您使用:

if command; then
    foo
else
    bar
fi

那么要么将被调用,要么不会同时被调用foobar当同时使用&&和 时||,可以采用两条路径:

$ [[ -d / ]] && {
> echo "Path 1 taken"
> false
> } || {
> echo "Path 2 taken"
> }
Path 1 taken
Path 2 taken
$

使用表单时,调用的if cmd; then foo; else bar; fi条件是返回false。使用表单时,调用的条件是返回false。barcmdcmd && foo || barbarcmd && foo

编辑:我刚刚注意到,在你的问题中,你承认你需要放在true块的末尾才能使你的版本正常工作。如果您愿意这样做,我不知道任何其他重大问题 - 但我认为,如果有任何可能,则需要您无条件添加“true”作为块中的最后一个命令的样式之前的命令可能会失败,只是保证您最终会忘记它,并且事情看起来会正常工作,直到实际情况并非如此。

答案2

在我看来,对于用任何其他语言编写的人来说,if-then-else 更容易阅读。但我的建议是仅对仅包含和
之一的单行代码使用短符号(使用 && 或 ||)。 有些代码像 &&||

[[ -d mustExist ]] || errorFunction "Dir mustExist is missing"
[[ -f toBeSend ]] && sendFile toBeSend
if [[ -d sometimes ]]; then
   writeTrueBlock
else
   writeFalseBlock
fi

编辑:新想法:这样写可能会更好

test -d mustExist || errorFunction "Dir mustExist is missing"
test -f toBeSend && sendFile toBeSend
if [[ -d sometimes ]]; then
   writeTrueBlock
else
   writeFalseBlock
fi

答案3

可读性和风格

我倾向于在脚本编写中大量使用&&和运算符。||

我什至在一条语句中使用多个,但仅在检查是否继续在当前区块中。

示例1:

for word in $list; do
    condition1 $word || continue
    condition2 $word || continue

    : do stuff with $word
    : do more stuff with $word
done

条件1条件2作为断言。我们得到了例外情况 让开,并继续执行这段代码应该执行的操作。

在这种情况下使用if……就有点尴尬了thenfi

替代符号:

示例2:

for word in $list; do
    if condition1 $word && condition2 $word; then
        : do stuff with $word
        : do more stuff with $word
    fi
done

例子2我们有另一个级别的缩进,而没有发生任何额外的事情。

例3:

for word in $list; do
    condition1 $word && condition2 $word || continue
    : do stuff with $word
    : do more stuff with $word
done

如果这两个条件可以简单地表达,我有时会像示例3一样将它们组合起来。


PS:我最初为 shell 程序员添加了一个练习:三个示例中只有两个是完全等效的。哪一个是奇怪的? 碰巧的是,我认为存在的差异并不存在。我实际上写了一个shpec测试:

describe "continue"
  it "discards last exit status"
    (for i in 1; do
     false || continue
     done
    )
    assert equal 0 $?
  end
end

shpec/continue_shpec.sh
continue
  discards last exit status
  1 examples, 0 failures

相关内容