案例陈述失败了吗?


68

在流行的命令式语言中,一旦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语句“跌落”到其余条件(如第一个示例)?

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

运行:

test.sh:

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

给出:

./test.sh:第6行:意外令牌附近的语法错误 ;&';' ./test.sh:
line 6:


2
相关(但不重复)的问题:切换掉线情况吗?(关于在|表达式中分隔多个模式的运算符case)。
TachyonVortex

Answers:


49

;&;;&运营商在bash 4.0中引入的,所以如果你想坚持一个五岁版本的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变量或环境变量。)


关于bash版本的有趣注释。
Resorath 2012年

哇!谢谢,我现在看到我的“新” MacBookPro 2012具有非常旧的2007 Bash:GNU bash,版本3.2.48(1)
发行

6
@AnneTheAgile,是的。bash 3.2是GPLv2,bash 4.0(及更高版本)是GPLv3,苹果公司“不喜欢” GPLv3(en.wikipedia.org/wiki/GPL_v3#Legal_Barrier_to_App_Stores)。当然,尽管您可以通过自制软件或Macports或类似软件轻松获得最新的支持。
geirha 2013年

1
@不会在bash和sh中出现,因为shell变量与环境变量和特殊的shell变量共享名称空间。
Geirha

1
@Will,“避免名称空间冲突”的一部分不在POSIX指定用于对操作系统和外壳有意义的变量的名称空间之内。该名称空间由标准定义为全大写字母名称的集合;请参阅pubs.opengroup.org/onlinepubs/9699919799/basedefs/…,请记住环境变量和shell变量共享一个名称空间。
查尔斯·达菲,

38

尝试这个:

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

2
谢谢(你的)信息。不过,我将第三种情况的“名称”更改为somethingElse
fotNelton,2015年

1
当我尝试此操作时,我syntax error near unexpected token `;'与保持联系;&。为什么是这样?
卡梅隆·哈德森

2
@CameronHudson,因为您使用的Bash版本早于4.0
Josh

6

使用;&不是很可移植,因为它需要bash(不是ashdash或其他最低sh要求),并且至少需要bash4.0或更高版本(并非在所有系统上都可用,例如macOS 10.14.6仍然仅提供bash 3.2.57)。

我认为,一种解决方法比很多方法更容易阅读,它if是循环并修改大小写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

2
“真正的sh”是什么,POSIX之前的版本(又称1970年代时代语法)Bourne?
查尔斯·达菲

2
@CharlesDuffy/bin/sh是一个Bourne外壳,是BASH,DASH,ASH以及POSIX标准的通用基础。这些外壳中的每一个都支持其他功能,某些功能是该外壳特有的,但它们与SH兼容,与其他一些外壳不同(csh和tcsh不兼容,zsh仅部分
兼容

3
伯恩(Bourne)是1970年代的贝壳。POSIX sh是1991/bin/sh年的规范。在现代系统上是POSIX,而不是Bourne。选择一个易于测试的差异,echo hello ^ cathello在Bourne上发出,因为^那里是管道字符。而在POSIX兼容的外壳程序中,它发出hello ^ cat作为输出,因为将^解析为的参数echo
查尔斯·达菲,

2
(顺便说一下,^-as-a-pipe-character的区别是GNU autoconf用来区分是在Bourne还是POSIX sh上使用的区别;也就是说,POSIX规范通常从早期的ksh中汲取了很多启发,从而使行为规范化最初是ksh扩展名)。
查尔斯·达菲

3
绝对有效的答案。许多嵌入式计算机附带灰烬,甚至Ubuntu中的sh都是破折号。对于那些壳,此答案是有效的。不知道为什么这会被否决,为什么我们要争论非bash,sh是否相关...它甚至是相当优雅和惯用的
Paulo Neves
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.