回答:
できません。case
フォールスルーを行う方法は、;;
セパレータを;&
(または;;&
)に置き換えることです。そして、それをifの中に入れるのは構文エラーです。
ロジック全体を通常の条件として記述できます。
if [ "$input" != "foo" ] || [ "$VAR" = 1 ]; then
one branch ...
else # $input = "foo" && $VAR != 1
another branch...
fi
if
。
ロジックを再構築することをお勧めします。代わりに「フォールスルー」コードを関数に入れます。
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
最初にテストし、次にに応じてフォールスルー(;&
a を使用case
)を実行するという意味で、テストを「裏返し」にし$input
ます。
これは、「フォールスルーを実行する」かどうかの問題は、実際には$input
ifにのみ依存するため$var
です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
VARをブール値に変換するには、テスト対象の値()に2つの値のみが必要であるため、if句が存在することを理解してください。VARをブール値にすることができる場合は、で0
(ではない1
)をテストし、case
を削除しif
ます。
あなたはフォールスルーをデフォルトにすることができますが、条件が満たされた場合にのみコードが実行されるという条件を置きます
#!/bin/bash
input='foo'
var='1'
case $input in
foo)
echo "Do fall through"
;& #always fall through
*)
if [ $var = "1" ] #execute only if condition matches
then
echo "fallthrough took place"
fi
esac
しかし、ilkkachuが示唆したように、スイッチではなく条件を使用することもできます。
誰かがあなたのコードを理解していないことについて不平を言ってもかまわない場合は、2つの条件の順序を入れ替えることができます。
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
フォールスルー自体はサポートしていません。しかし*)
、&&
後で置き換えてesac
、他のブランチの戻り値を尊重することができます。
新規;&
および;;&
演算子は
4.0
で導入されましたBash
が、どちらも同じような状況で役立つ場合がありますが、あなたの場合は役に立たないと思います。これはman bash
、これらの演算子について言うものです:
もし;; 演算子を使用すると、最初のパターン一致の後に後続の一致は試行されません。;;の代わりに;&を使用する 次のパターンのセットに関連付けられたリストから実行を続行します。;;の代わりに;;&を使用する シェルに、ステートメント内の次のパターンリストがある場合はそれをテストさせ、一致した場合に関連リストを実行させます。
言い換えれば、;&
我々はそれを知っているから通って、と秋であるC
と
;;&
なりますが、bash
代わりに返すの残りのケースを確認し
case
、完全にブロック。;;&
実際の動作の良い例を/programming//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
コードの一部からそこにあるものにジャンプしようとしてい*)
ますか?それはフォールスルーと呼ばれるものとは完全に異なるため、質問の言い回しを少し誤解させるだけです。