■break、continue、return、exit

せ> type break
break is a shell builtin
せ> type continue
continue is a shell builtin
せ> type return
return is a shell builtin

 

■bashにgotoやjumpのようなコマンドはない

せ> type goto
-bash: type: goto: not found
せ> type jump
-bash: type: jump: not found

 

■continue文はfor、while、またはuntilループで次の繰り返しに飛ぶコマンド。

・ifブロックやcaseブロックから途中で抜けるコマンドはない。

・ラベル付きcontinue文はない。

※代わりに深さの数値を引数を指定できる

 

■break文はfor、while、またはuntilループを途中で抜けるコマンド。

・ifブロックやcaseブロックから途中で抜けるコマンドはない。

・ラベル付きbreak文はない。

※代わりに深さの数値を引数を指定できる

※javaではbreak文でswitch文を抜けるがbashでcaseブロックから抜ける場合は「;;」文

 

※プログラミング言語によってcontinue、break、return、exitで条件分岐ブロック、ループから抜けたり、call元に戻る文法が異なる。

※プログラミング言語によってgotoやjumpがあったりなかったりする

 

【課題】

プログラミング言語ごとに、ループ、条件分岐、配列、関数(メソッド)、論理式、ブロック抜け、関数から戻り、宣言、変数定義などの文法がそれぞれ異なるので、これらの文法項目ごとに、各言語ごとの構文を一覧表にまとめる。(とくに留意事項を含める)

 

■ifブロックから抜けれる?

せ> cat if.sh
#!/bin/bash
read X
if [ $X -gt 0 ] 2> /dev/null;then
    echo X is larger than 0
    elif [ $X -eq 0 ] 2> /dev/null;then
        echo X is 0
    elif [ $X -lt 0 ] 2> /dev/null;then
        echo X is less than 0
    else
        echo X is not integer
fi

echo おわり

せ> bash ./if.sh
1
X is larger than 0

おわり
せ> bash ./if.sh
0
X is 0

おわり
せ> bash ./if.sh
-9223372036854775808    
←2の63乗
X is less than 0

おわり
せ> bash ./if.sh
-9223372036854775809
X is not integer

おわり
せ> bash ./if.sh
うんこ

X is not integer

おわり

 

【検証1】 if文の途中でbreak文

せ> cat if_break.sh
#!/bin/bash
read X
if [ $X -gt 0 ] 2> /dev/null;then
    echo X is larger than 0
    elif [ $X -eq 0 ] 2> /dev/null;then
        echo X is 0

# insert break
    break

    elif [ $X -lt 0 ] 2> /dev/null;then
        echo X is less than 0
    else
        echo X is not integer
fi
echo おわり

せ> bash ./if_break.sh
0

X is 0
./if_break.sh: line 8: break: only meaningful in a `for', `while', or `until' loop
おわり

せ> bash ./if_break.sh
うんこ

X is not integer
おわり

 

【検証2】 if文の途中でcontinue文

せ> cat if_continue.sh
#!/bin/bash
read X
if [ $X -gt 0 ] 2> /dev/null;then
    echo X is larger than 0
    elif [ $X -eq 0 ] 2> /dev/null;then
        echo X is 0

# insert continue
    continue

    elif [ $X -lt 0 ] 2> /dev/null;then
        echo X is less than 0
    else
        echo X is not integer
fi
echo おわり

せ> bash ./if_continue.sh
1
X is larger than 0
おわり

せ> bash ./if_continue.sh
0

X is 0
./if_continue.sh: line 8: continue: only meaningful in a `for', `while', or `until' loop
おわり

せ> bash ./if_continue.sh
うんこ
X is not integer
おわり

※ループ内じゃないところでbreakやcontinueを使えない

せ> type goto
-bash: type: goto: not found

※「goto」というコマンド、bashシンボルはない。

※if文やcase文の途中から抜ける方法はない?

 

 

■continue文

 

【検証3】 for文とcontinue文

せ> for ((i=1;i<=4;i++));do echo $iループ目;echo ち;[ $i -eq 2 ] && continue;echo んこ;done
1ループ目

んこ

2ループ目
ち                        ←このルー
プ回の途中で次のループに飛んでる
3ループ目

んこ

4ループ目

んこ

せ> echo $?
0

 

【検証4】 while文とcontinue文

せ> i=0;while ((i<=4));do ((i++));echo $iループ目;echo ち;

[ $i -eq 2 ]  && continue;echo んこ;done
1ループ目

んこ

2ループ目
ち                        ←このルー
プ回の途中で次のループに飛んでる
3ループ目

んこ
4ループ目

んこ
5ループ目

んこ

せ> echo $?
0

 

【検証5】2重ループの内側のループでcontinue文

せ> cat double_loop.sh
#!/bin/bash
for((i=1;i<=3;i++))
do
    for((j=1;j<=3;j++))
    do
        echo iは$iでjは$j
        [ $i -eq 2 ] && continue
        echo あばばばば
    done
done

せ> bash ./double_loop.sh
iは1でjは1
あばばばば
iは1でjは2
あばばばば
iは1でjは3
あばばばば

iは2でjは1      ←i=2の時だけ「あばばばば」が無い
iは2でjは2      ←i=2の時だけ「あばばばば」が無い
iは2でjは3      ←i=2の時だけ「あばばばば」が無い
iは3でjは1      ←i=2の時だけ「あばばばば」が無い

あばばばば
iは3でjは2
あばばばば
iは3でjは3
あばばばば

せ> echo $?
0

 

【検証6】2重ループの内側のループでcontinue文 その2

せ> cat double_loop2.sh
#!/bin/bash
for((i=1;i<=3;i++))
do
    for((j=1;j<=3;j++))
    do
        echo iは$iでjは$j
        [ $j -eq 2 ] && continue
        echo あばばばば
    done
done

せ> bash ./double_loop2.sh
iは1でjは1
あばばばば

iは1でjは2      ←j=2の時だけ「あばばばば」が無い
iは1でjは3
あばばばば
iは2でjは1
あばばばば

iは2でjは2      ←j=2の時だけ「あばばばば」が無い
iは2でjは3
あばばばば
iは3でjは1
あばばばば

iは3でjは2      ←j=2の時だけ「あばばばば」が無い
iは3でjは3
あばばばば

せ> echo $?
0

 

 

■break文

 

【検証7】 for文とbreak文

せ> for ((i=1;i<=4;i++));do echo $iループ目;echo ち;[ $i -eq 2 ] && break;echo んこ;done
1ループ目

んこ

2ループ目

せ> echo $?
0

 

【検証8】 while文とbreak文

せ> i=0;while ((i<=4));do ((i++));echo $iループ目;echo ち; 

[ $i -eq 2 ] && break;echo んこ;done
1ループ目

んこ

2ループ目

せ> echo $?
0

 

【検証9】2重ループの内側のループでbreak文

せ> cat double_loop3.sh
#!/bin/bash
for((i=1;i<=3;i++))
do
    for((j=1;j<=3;j++))
    do
        echo iは$iでjは$j
        [ $i -eq 2 ] && break
        echo あばばばば
    done
done

せ> bash double_loop3.sh
iは1でjは1
あばばばば
iは1でjは2
あばばばば
iは1でjは3
あばばばば

iは2でjは1      ←i=2のbreakのところで内側のループから抜けた
iは3でjは1
あばばばば
iは3でjは2
あばばばば
iは3でjは3
あばばばば

せ> echo $?
0

 

【検証10】2重ループの内側のループでbreak文 ―その2―

せ> cat double_loop4.sh
#!/bin/bash
for((i=1;i<=3;i++))
do
    for((j=1;j<=3;j++))
    do
        echo iは$iでjは$j
        [ $j -eq 2 ] && break
        echo あばばばば
    done
done

せ> bash ./double_loop4.sh
iは1でjは1
あばばばば

iは1でjは2      ←j=2のbreakのところで内側のループから抜けた
iは2でjは1
あばばばば

iは2でjは2      ←j=2のbreakのところで内側のループから抜けた
iは3でjは1
あばばばば

iは3でjは2      ←j=2のbreakのところで内側のループから抜けた

せ> echo $?
0

 

【検証11】2重ループの内側のループでbreak文 ―その3―

せ> cat double_loop5.sh
#!/bin/bash
for((i=1;i<=3;i++))
do
    for((j=1;j<=3;j++))
    do
    [ $j -eq 2 ] && break
        echo iは$iでjは$j
        echo あばばばば
    done
done

せ> bash ./double_loop5.sh
iは1でjは1
あばばばば
iは2でjは1
あばばばば
iは3でjは1
あばばばば
      ←j=2のbreakのところで内側のループから抜けた

せ> echo $?
0

 

 

■continue "深さ"

 

【検証12】 continue 2

せ> cat double_loop6.sh
#!/bin/bash
for((i=1;i<=3;i++))
do
    for((j=1;j<=3;j++))
    do
        echo iは$iでjは$j
        [ $i -eq 2 ] && continue 2
        echo あばばばば
    done
done

せ> bash ./double_loop6.sh
iは1でjは1
あばばばば
iは1でjは2
あばばばば
iは1でjは3
あばばばば

iは2でjは1            ←【検証5】と比較。【検証9】の結果と同じになった。つまり「continue 2」実行後内側のループから抜け出た
iは3でjは1
あばばばば
iは3でjは2
あばばばば
iは3でjは3
あばばばば

せ> echo $?
0

 

 

■break "深さ"

 

【検証13】  break 2

せ> cat double_loop7.sh
#!/bin/bash
for((i=1;i<=3;i++))
do
    for((j=1;j<=3;j++))
    do
        echo iは$iでjは$j
        [ $i -eq 2 ] && break 2
        echo あばばばば
    done
done

せ> bash ./double_loop7.sh
iは1でjは1
あばばばば
iは1でjは2
あばばばば
iは1でjは3
あばばばば

iは2でjは1               ←【検証9】と比較。「break 2」実行後、内側と外側のループを一気に抜け出た

せ> echo $?
0

 

 

■exit文

 

【検証14】  スクリプトで実行

せ> type exit
exit is a shell builtin

せ> cat exit.sh
#!/bin/bash
read X;[[ $X -gt 0 ]] && exit 1 || [[ $X -eq 0 ]] && exit 2 ||  [[ $X -lt 0 ]] && exit 3   ←①

せ> bash ./exit.sh
1
せ> echo $?
1
せ> bash ./exit.sh
0
せ> echo $?
2
せ> bash ./exit.sh
-2
せ> echo $?
3
せ> bash ./exit.sh
hoge
せ> echo $?

2                 ←変数「hoge」はnullなので値は0と評価された

※①をカレントシェルからワンライナーで実行するとカレントシェルセッションが終了する

 

【検証15】  関数で実行

せ> bash
せ> function exit_func {   
               ←②
> read X;[[ $X -gt 0 ]] && exit 1 || [[ $X -eq 0 ]] && exit 2 ||  [[ $X -lt 0 ]] && exit 3
> }

せ> exit_func
1
exit
せ> echo $?
1
せ> bash
せ> function exit_func {
> read X;[[ $X -gt 0 ]] && exit 1 || [[ $X -eq 0 ]] && exit 2 ||  [[ $X -lt 0 ]] && exit 3
> }
せ> exit_func
0

exit
せ> echo $?
2
せ> bash
せ> function exit_func {
> read X;[[ $X -gt 0 ]] && exit 1 || [[ $X -eq 0 ]] && exit 2 ||  [[ $X -lt 0 ]] && exit 3
> }
せ> exit_func
-3

exit
せ> echo $?
3

※②をカレントシェルからワンライナーで実行するとカレントシェルセッションが終了する

 

 

■retruen文

 

【検証16】  スクリプトの中のretruen文

せ> cat return.sh                    ←③
#!/bin/bash
read X;[[ $X -gt 0 ]] && return 1 || [[ $X -eq 0 ]] && return 2 ||  [[ $X -lt 0 ]] && return 3

せ> bash return.sh
5
return.sh: line 2: return: can only `return' from a function or sourced script

せ> source return.sh
1
せ> echo $?
1
せ> source return.sh
0
せ> echo $?

2
せ> source return.sh
-800
せ> echo $?

3

※③をbashコマンドによりサブシェルで実行するとエラーになる

※③をsourceコマンドによりカレントシェルで実行できる

 

【検証17】  関数の中のreturn文

関数の最後には return コマンドを指定し、その引数として与えた値が関数の終了ステータスとなる。
return コマンドの引数に指定できる値は、0 もしくは 1~255 の正の整数値のみである。マイナスの値も指定可能であるが、-1 を指定した場合は結果的に 255 になる。
この return コマンドは省略可能で、省略された場合は関数内で最後に実行されたコマンドの終了ステータスが、関数自体の終了ステータスとなる。

 

せ> function return_func {               ←④
> read X;[[ $X -gt 0 ]] && return 1 || [[ $X -eq 0 ]] && return 2 ||  [[ $X -lt 0 ]] && return 3
> }
せ> return_func
100

せ> echo $?
1
せ> function return_func {
> read X;[[ $X -gt 0 ]] && return 1 || [[ $X -eq 0 ]] && return 2 ||  [[ $X -lt 0 ]] && return 3
> }
せ> return_func
0
せ> echo $?

2
せ> function return_func {
> read X;[[ $X -gt 0 ]] && return 1 || [[ $X -eq 0 ]] && return 2 ||  [[ $X -lt 0 ]] && return 3
> }
せ> return_func
-60
せ> echo $?

3

※④をカレントシェルからワンライナーで実行できる