在 bash 中,有没有办法可以编写更短的(if or)语句?

在 bash 中,有没有办法可以编写更短的(if or)语句?
if [ foo = bar -o foo = car -o foo = jar -o foo = foo ]
  then
    echo yes
fi

为了让事情更有条理,我想尝试将其与列表匹配,例如

if [ foo = {bar,car,jar,foo} ] ; then

显然花括号扩展方法不起作用,否则我就不会在这里了!但我想知道这样的事情是否有可能实现。

答案1

它看起来像是你代码中的一个错误,但我们可以将其重构得非常小......

如果你真的用 写了你的表达式[ foo = bar -o foo = car -o foo = jar -o foo = foo ],那么它就可以简化为:

echo yes

这个测试总是正确的,因为foo = foo总是正确的,而这又是因为文字字符串foo总是与其自身相同。

虽然您已经澄清了这种语法没有出现在您实际使用的代码中,但我保留了这个介绍部分,因为这样做是一个常见的错误,尤其是对于新手来说。尝试以foo这种方式检查的值在任何 Bourne 风格的 shell 中都不起作用——要使用 检查变量的值[,您必须使用 执行参数扩展$(见下文)。这个问题的这个特定方面并不是特定于 shell 的;例如,这是 7 个 Bourne 风格 shell 中的测试

修复原始代码

也许你想检查价值变量foo(即其内容(而不是其名称)与这些字符串相对应。在这种情况下,您的原始代码将变成如下形式:

if [ "$foo" = bar -o "$foo" = car -o "$foo" = jar -o "$foo" = foo ]; then
    echo yes
fi

使用短路运算&&符可以稍微缩短它:

[ "$foo" = bar -o "$foo" = car -o "$foo" = jar -o "$foo" = foo ] && echo yes

但它仍然比你可能喜欢的更长、更复杂、更重复。所以,继续……

通过模式匹配缩短格式

您可以使用该[[工具的内置正则表达式匹配运算符:

[[ $foo =~ ^(bar|car|jar|foo)$ ]] && echo yes

虽然使用case可能是最常见的方式,[[但是使用的方式=~是:

  • 与紧凑使用的长度相同case(见下文)
  • 可以说更符合原始代码的逻辑,因为它使用了[[,其工作方式与测试表达式非常相似。

所以你可能更喜欢这个。这是我可能会使用的在 bash 中执行此操作的方法。

如果你想做类似的事情,但使用grep而不是[[with进行匹配=~,这是类似的:

grep -Eq '^(bar|car|jar|foo)$' <<< "$foo" && echo yes

或这个:

grep -Fqe{bar,car,jar,foo} <<< "$foo" && echo yes

一行代码case

作为塞格说,可以简化为使用case代替if[。这是经典的,也可能是最常见的方法。

方法Serg 的回答运行得很好,但对于你正在重构的特定代码,我们可以编写一些更简单的代码,只需使用一个模式即可case。最后不需要进行全能*)匹配。如果字符串与任何模式都不匹配,控制权将直接通过 case 构造,并且不会执行任何命令,这相当于if没有 的构造else

case $foo in bar|car|jar|foo) echo yes;; esac

这使得它足够简短和简单,可以轻松地放在一行中(这似乎就是您想要的),并且易于阅读。此方法还可以移植到除 bash 之外的 Bourne 风格的 shell。

答案2

我建议使用格结构。例如:

case $foo in
    foo|car|bar|jar) echo yes ;;
    *) ;;
esac

*)如果您愿意,您可以在和之间添加一个命令,当不匹配、、或时;;执行该命令。例如,您可以使用或类似的东西打印一条消息。$foofoocarbarjarecho 'wrong input'

答案3

更短一点:

[[ $foo =~ ^([bcj]ar|foo)$ ]] && echo yes

这种方式与以 开头、后跟或完全匹配的正则$foo表达式进行匹配。bcjarfoo

这使用&&运算符作为短路,echo yes仅当[[ $foo =~ ^([bcj]ar|foo)$ ]]表达式计算结果为真时才运行。

如果这段代码太紧凑,不便于阅读,你仍然可以使用完整的 if 结构,它的作用完全相同,但可读性更强:

if [[ $foo =~ ^([bcj]ar|foo)$ ]]
then
    echo yes
fi

相关内容