案例陈述失败了吗?

在流行的命令式语言中,一旦 case 语句匹配,switch 语句通常会“落到”下一个级别。

例如:

int a = 2;
switch(a)
{
case 1:
print "quick ";
case 2:
print "brown ";
case 3:
print "fox ";
break;
case 4:
print "jumped ";
}

会印上“棕色狐狸”。

但是 bash 中的代码是相同的吗

A=2
case $A in
2)
echo "QUICK"
;&
2)
echo "BROWN"
;&
3)
echo "FOX"
;&
4)
echo "JUMPED"
;&
esac

只印刷“棕色”

如何使 bash 中的 case 语句“ fall through”与第一个示例一样适用于其余条件?

(编辑: Bash 版本3.2.25,; & 语句(来自维基百科)导致语法错误)

跑步:

Test.sh:

#!/bin/bash
A=2
case $A in
1)
echo "QUICK"
;&
2)
echo "BROWN"
;&
3)
echo "FOX"
;&
esac

给予:

./test.sh: 第6行: 意外标记附近的语法错误 < code > ;’./test.sh:
第6行: ; &’

60063 次浏览

;&;;&操作符是在 bash 4.0中引入的,所以如果您想继续使用5年前的 bash 版本,就必须重复编写代码,或者使用 if

if (( a == 1)); then echo quick; fi
if (( a > 0 && a <= 2)); then echo brown; fi
if (( a > 0 && a <= 3)); then echo fox; fi
if (( a == 4)); then echo jumped; fi

或者找到其他方法来实现真正的目标。

(值得注意的是,不要使用所有的大写变量名有覆盖特殊 shell 变量或环境变量的风险。)

试试这个:

case $VAR in
normal)
echo "This doesn't do fallthrough"
;;
fallthrough)
echo -n "This does "
;&
somethingelse)
echo "fall-through"
;;
esac

使用 ;&不是很便携,因为它需要 bash(而不是 ashdash或任何其他最小的 sh) ,并且它至少需要 bash4.0或更新(不是所有系统都可用,例如 macOS 10.14.6仍然只提供 bash 3.2.57)。

一个我认为比很多 if更好的解决方法是循环和修改 case var:

#!/bin/sh


A=2
A_BAK=$A
while [ -n "$A" ]; do
case $A in
1)
echo "QUICK"
A=2
;;


2)
echo "BROWN"
A=3
;;


3)
echo "FOX"
A=4
;;


4)
echo "JUMPED"
A=""
;;
esac
done
A=$A_BAK

这里有一个概念证明: https://www.onlinegdb.com/0ngLPXXn8

Bash 开关带有终止,通过函数和标志实现

#! /bin/sh


switch_fallthrough() {
[ $# = 0 ] && { echo no value >&2; return; }
local f= # fall through
[ "$1" = 1 ] && { echo quick; f=1; }
[ $f ] || [ "$1" = 2 ] && { echo brown; f=1; }
[ $f ] || [ "$1" = 3 ] && { echo fox; return; }
[ $f ] || [ "$1" = 4 ] && echo jumped
return 1 # error = no case did match
}


switch_fallthrough "2"
# brown
# fox

使用带有模式更改的 case 语句序列:

#!/bin/sh


a="2"
case "$a" in
"1")
echo "QUICK"
;;
esac
case "$a" in
"1" | "2")
echo "BROWN"
;;
esac
case "$a" in
"1" | "2" | "3")
echo "FOX"
;;
esac
case "$a" in
"4")
echo "JUMPED"
;;
esac

好处:

  • 遵循原问题的格式
  • 可以使用任何符合 POSIX 的 sh,包括旧版本的 Bash
  • a的无序字符串值,如“ apple”、“ pear”、“ banana”、“ tree”将起作用
  • 没有后向分支的控制流是直接的

缺点:

  • 需要更多的字符,因为有四个 case 语句而不是一个

注意,对于非环境变量,小写的 a优于大写的 A,对于一般情况下 a中可能有空格的情况,应该引用 $a和大小写模式。对于简单的情况,可以删除引用。