Answers:
我建议重组您的逻辑:将“ fallthrough”代码放入函数中:
fallthrough() { echo 'fallthrough worked!'; }
for input in foo bar; do
for var in 1 2; do
echo "$input $var"
case $input in
foo)
if (( var == 1 )); then
echo "falling through"
fallthrough
else
echo "not falling through"
fi
;;
*) fallthrough;;
esac
done
done
输出
foo 1
falling through
fallthrough worked!
foo 2
not falling through
bar 1
fallthrough worked!
bar 2
fallthrough worked!
以下脚本从某种意义上说使您的测试“由内而外”,即我们$var
首先进行测试,然后根据进行插入(;&
在中使用case
)$input
。
我们这样做是因为是否“执行失败”实际上仅取决于$input
if $var
is 1
。如果还有其他值,则甚至不必询问是否执行失败检查。
#/bin/bash
input='foo'
var='1'
case $var in
1)
case $input in
foo)
echo 'perform fallthrough'
;&
*)
echo 'fallthough worked'
esac
;;
*)
echo 'what fallthrough?'
esac
或者,如果没有case
:
if [ "$var" -eq 1 ]; then
if [ "$input" = 'foo' ]; then
echo 'perform fallthrough'
fi
echo 'fallthough worked'
else
echo 'what fallthrough?'
fi
*)
。已经有我的+1。
不是我会做的事,但是您可以通过以下方式实现一些目标:
shopt -s extglob # for !(*)
default='*'
case $input in
(foo)
if [ "$VAR" = 1 ]; then
echo going for fallthrough
else
echo disabling fallthrough
default='!(*)'
fi ;;&
($default)
echo fallthrough
esac
一次测试两个变量(bash 4.0-alpha +):
#!/bin/bash
while (($#>1)); do
input=$1 VAR=$2
echo "input=${input} VAR=${VAR}"; shift 2
if [ "$VAR" = 1 ]; then new=1; else new=0; fi
case $input$new in
foo0) echo "do not perform fallthrough" ;;
foo*) echo "perform fallthrough" ;&
*) echo "fallthrough worked!" ;;
esac
echo
done
在测试中:
$ ./script foo 0 foo 1 bar baz
input=foo VAR=0
do not perform fallthrough
input=foo VAR=1
perform fallthrough
fallthrough worked!
input=bar VAR=baz
fallthrough worked!
干净简单。
了解测试值($new
)必须只有两个可能的值,这就是为什么存在if子句才能将VAR转换为布尔值的原因。如果可以将VAR设为布尔值,请在中测试0
(不是1
)case
并删除if
。
如果您不介意有人抱怨他们不了解您的代码,则只需切换两个条件的顺序即可:
input="foo"
VAR="1"
if
case $input in
foo)
[ $VAR = "1" ]
;;
esac
then
echo "fallthrough worked!"
fi
要么:
input="foo"
VAR="1"
case $input in
foo)
[ $VAR = "1" ]
;;
esac &&
echo "fallthrough worked!"
简单明了(至少对我而言)。case
不支持失败本身。但是您可以*)
使用&&
after 替换esac
为使其尊重其他分支的返回值。
在
4.0中引入了 new ;&
和;;&
operator
,尽管它们在类似情况下都可能有用,但我认为它们在您的情况下没有用。这是说,这些运营商:Bash
man bash
如果;; 使用运算符时,在第一个模式匹配之后将不尝试后续匹配。用;&代替;; 使执行继续与下一组模式相关联的列表。用;;&代替;; 使外壳测试语句中的下一个模式列表(如果有),并在成功匹配后执行任何关联的列表。
换句话说,;&
就是通过一个秋天,因为我们知道从它C
和
;;&
品牌bash
检查剩余的情况下,而不是从返回
case
块完全。您可以;;&
在这里找到一个很好的实际例子:https : //stackoverflow.com/a/24544780/3691891。
话虽如此,您的脚本中;&
也;;&
不能使用它,因为它们都*)
将一直运行。
以下脚本可以正常工作,并且可以执行您想要的操作,而无需重新排列逻辑,但是仅将其视为示例,并且永远不要依赖它,因为它太脆弱了。我从这里接受了这个想法 :
#!/usr/bin/env bash
function jumpto
{
label=$1
cmd=$(sed -n "/$label:/{:a;n;p;ba};" "$0" | grep -v ':$')
cmd=$(echo "$cmd" | sed 's,;;,,')
cmd=$(echo "$cmd" | sed 's,esac,,')
eval "$cmd"
}
input="foo"
VAR="1"
case $input in
foo)
if [ $VAR = "1" ]; then
printf "perform fallthrough\n"
jumpto ft
else
printf "do not perform fallthrough\n"
fi
;;
*)
ft:
echo "fallthrough worked!"
;;
esac
jumpto
函数返回并执行其后的所有内容。这等效于在块之间的继续执行,ft:
并且这;;
是一个巧合,因为这jumpto
是与跳转到的块相同的复杂命令中的最后一条命令。
if [ $VAR -eq 1 ]; then
部分代码跳转到其中的任何内容*)
?因为这与所谓的失败完全不同,所以使您的问题措辞稍有误导性。