if [ foo = bar -o foo = car -o foo = jar -o foo = foo ]
then
echo yes
fi
Run Code Online (Sandbox Code Playgroud)
为了使事情更有条理,我想尝试将其与列表匹配,例如
if [ foo = {bar,car,jar,foo} ] ; then
Run Code Online (Sandbox Code Playgroud)
显然花括号展开法没有用,要不然我就不会在这里了!但我想知道这样的事情是否可能。
Eli*_*gan 15
如果你真的用 写了你的表达式[ foo = bar -o foo = car -o foo = jar -o foo = foo ],那么它可以被简化为:
echo yes
Run Code Online (Sandbox Code Playgroud)
此测试始终为真,因为foo = foo始终为真,而这又是因为文字字符串foo始终与其自身相同。
尽管您已经澄清此语法并未出现在您真正使用的代码中,但我保留了这个介绍性部分,因为这样做是一个常见的错误,尤其是在新手中。尝试以foo这种方式检查值在任何 Bourne 风格的 shell 中都不起作用——要检查带有 的变量的值[,您必须使用 执行参数扩展$(见下文)。问题的这一特定方面不是特定于 shell 的。例如,这是在 7 个 Bourne-style shell 中的测试。
也许不是你的意思是检查值的的foo变量(即,它的内容,而不是它的名字)对那些字符串。在这种情况下,您的原始代码将变成:
echo yes
Run Code Online (Sandbox Code Playgroud)
这可以通过短路&&运算符稍微缩短:
if [ "$foo" = bar -o "$foo" = car -o "$foo" = jar -o "$foo" = foo ]; then
echo yes
fi
Run Code Online (Sandbox Code Playgroud)
但它仍然比您可能喜欢的更长、更复杂和更重复。所以,继续……
您可以使用该[[工具的内置正则表达式匹配运算符:
[ "$foo" = bar -o "$foo" = car -o "$foo" = jar -o "$foo" = foo ] && echo yes
Run Code Online (Sandbox Code Playgroud)
虽然使用case可能是最常见的方式,但[[使用的=~是:
case(见下文)[[,它的工作方式很像测试表达式。所以你可能更喜欢那个。 这是我可能会使用的方法,在 bash 中执行此操作。
如果你想做类似的事情但匹配 usinggrep而不是[[with =~,这是类似的:
[[ $foo =~ ^(bar|car|jar|foo)$ ]] && echo yes
Run Code Online (Sandbox Code Playgroud)
或这个:
grep -Eq '^(bar|car|jar|foo)$' <<< "$foo" && echo yes
Run Code Online (Sandbox Code Playgroud)
case正如Serg 所说,可以使用case代替if和来简化[。这是经典的方式,可能也是最常见的方式。
Serg 的答案中的方法非常有效,但是对于您正在重构的特定代码,我们可以编写更简单的内容,只需使用case. 没有必要在最后进行一场全面的*)比赛。如果字符串与任何模式都不匹配,则控制只会通过 case 构造并且不执行任何命令,这相当于您的if构造没有else.
grep -Fqe{bar,car,jar,foo} <<< "$foo" && echo yes
Run Code Online (Sandbox Code Playgroud)
这使得它足够短和简单,可以很容易地适应——并且是可读的——在一行上(这似乎是你正在寻找的)。此方法也可移植到 bash 以外的 Bourne 风格的 shell。
Ser*_*nyy 10
我建议使用案例结构。就像是:
case $foo in
foo|car|bar|jar) echo yes ;;
*) ;;
esac
Run Code Online (Sandbox Code Playgroud)
如果您愿意,可以在、、、 或不匹配时在*)和之间添加;;要执行的命令。例如,您可以打印带有或类似内容的消息。$foofoocarbarjarecho 'wrong input'