案例陈述落实?

Res*_*ath 52 bash

在流行的命令式语言中,一旦case语句匹配,switch语句通常会"落到"下一级.

例:

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

会印出"棕色狐狸".

但是bash中的代码相同

A=2
case $A in
2)
  echo "QUICK"
  ;&
2)
  echo "BROWN"
  ;&
3)
  echo "FOX"
  ;&
4)
  echo "JUMPED"
  ;&
esac
Run Code Online (Sandbox Code Playgroud)

只打印"布朗"

如何将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
Run Code Online (Sandbox Code Playgroud)

得到:

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

gei*_*rha 36

;&;;&运营商在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
Run Code Online (Sandbox Code Playgroud)

或者找到其他方法来实现目标.

(另请注意,不要使用所有大写变量名.您可能会覆盖特殊的shell变量或环境变量.)

  • @AnneTheAgile,是的.bash 3.2是GPLv2,bash 4.0(和更新版本)是GPLv3,而Apple"不喜欢"GPLv3(http://en.wikipedia.org/wiki/GPL_v3#Legal_Barrier_to_App_Stores).当然,虽然你可以很容易地获得最近的自制或macports或类似的bash. (4认同)
  • @Will 不在 bash 和 sh 中,因为 shell 变量与环境变量和特殊 shell 变量共享命名空间。 (2认同)
  • @Will,“避免命名空间冲突”的一部分是远离 POSIX 指定用于对操作系统和 shell 有意义的变量的命名空间。该命名空间由标准定义为全大写名称的集合;请参阅 https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html,请记住环境和 shell 变量共享名称空间。 (2认同)

Ren*_*amp 31

试试这个:

case $VAR in
normal)
    echo "This doesn't do fallthrough"
    ;;
fallthrough)
    echo -n "This does "
    ;&
somethingelse)
    echo "fall-through"
    ;;
esac
Run Code Online (Sandbox Code Playgroud)

  • @CameronHudson 因为您使用的 Bash 版本早于 4.0 (3认同)
  • 谢谢(你的)信息.我会改变第三种情况的"名称",例如改为"somethingElse". (2认同)
  • 当我尝试这样做时,我在带有“;&amp;”的行上收到“意外标记\`;'”附近的语法错误。为什么是这样? (2认同)

Mec*_*cki 9

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

我认为比很多if's更易于阅读的解决方法是循环并修改 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
Run Code Online (Sandbox Code Playgroud)

  • Bourne 是 20 世纪 70 年代的外壳。POSIX sh 是 1991 年的规范。现代系统上的“/bin/sh”是 POSIX,**不是** Bourne。为了选择一个易于测试的差异,“echo hello ^ cat”将在 Bourne 上发出“hello”,因为“^”是那里的管道字符;而在兼容 POSIX 的 shell 中,它会发出“hello ^ cat”作为输出,因为“^”被解析为“echo”的参数。 (4认同)
  • @CharlesDuffy `/bin/sh` 是一个 Bourne shell,是 BASH、DASH、ASH 以及 POSIX 标准的共同基础。这些 shell 中的每一个都支持附加功能,其中一些是该 shell 所独有的,但它们都是 SH 兼容的,与其他一些 shell 不同(csh 和 tcsh 不支持,zsh 仅部分支持) (3认同)
  • 绝对有效的答案。许多嵌入式机器附带 ash,甚至 ubuntu 中的 sh 也是 dash。对于那些外壳,这个答案是有效的。不知道为什么这被否决了,为什么我们争论非 bash, sh 是否相关......它甚至非常优雅和惯用 (3认同)
  • “真正的‘sh’”是什么,前 POSIX(又名 1970 年代语法)Bourne? (2认同)
  • (顺便说一句,“^”作为管道字符的区别是 GNU autoconf 用于区分它是在 Bourne 还是 POSIX sh 上的区别;也就是说,POSIX 规范通常从早期的 ksh 中汲取了很多灵感,并且因此,最初是 ksh 扩展的行为被编码)。 (2认同)