今回は、繰り返し処理を中断する際に使用する「break」と「continue」を解説します。
「for」や「while」のdo~doneの中で処理を中断したい場合は、「break」または「continue」を使用します。
breakの場合、“繰り返し処理全体”を終了します。例えば、while文の中に書かれていた場合、whileのブロック全体を終了して、doneの後ろの処理に進みます。
対して、continueは“繰り返し内の処理”を中断します。繰り返し処理そのものは続行されるので、繰り返しの最初、つまりwhileの行に戻ります。
繰り返し処理そのものを終わらせたい場合は、breakを使用します。
次のスクリプトでは、readコマンドでキーボードからの入力を読み込み(スクリプト内(1))、case文で読み込んだ内容によって処理を分岐させています。
- #! /bin/bash
- echo -n "Say hello? [y/n] " #最初にメッセージを表示する
- while read s; do #標準入力を受け取って変数sにセット(1)
- case "$s" in #変数sで分岐
- "y") echo "Hello!";; #「y」の場合、Hello!とあいさつ(2)
- "n") echo "ok"; break;; #「n」ならwhile文を終了(3)
- *) echo "input [y] or [n]";; #それ以外の場合はメッセージを表示(4)
- esac
- echo -n "Again? [y/n] " #メッセージを表示してwhileに戻る(5)
- done
- echo "bye!" #最後にメッセージを表示(6)
入力した文字が「y」なら、echoコマンドで「Hello!」と表示します(同(2))。「n」ならば「ok」と表示後、breakで処理を中断します(同(3))。それ以外の文字が入力された場合には、「input [y] or [n]」と表示して処理を続行します(同(4))。
なお、入力前のメッセージ、つまりreadコマンドの直前に実行されるechoコマンドでは、メッセージ表示後に改行しないように「-n」オプションを付けています。
- $ chmod +x sayhello
- $ ./sayhello
- Say hello? [y/n] y[Enter] ← 最初のメッセージの後、(1)のreadで入力待ちしているので「y」と入力して[Enter]
- Hello!
- again? [y/n] aaa[Enter] ← case文が終了して、(5)が表示されて(1)に戻って入力待ちしているので「aaa」と入力して[Enter]
- input [y] or [n] ← 「y」でも「n」でもないので(3)のメッセージが表示された
- again? [y/n] n[Enter] ← case文が終了して(5)が表示、(1)のreadに対し「n」と入力して[Enter]
- ok ← (3)のメッセージを表示してwhile文を終了
- bye! ← (6)のメッセージが表示された
このスクリプトでは、キーボードで[n]を入力したときにbreakで終了しています。
[CTRL]+[D]でreadコマンドに対して入力を終了させた場合、そして[CTRL]+[C]でスクリプトを中断した場合と比較してみましょう。
- $ ./sayhello
- Say hello? [y/n] n ← (1)のreadに対し[n]を入力
- ok ← (3)でokと表示してbreak
- bye! ← (3)のbreakでwhileを抜けて(6)のメッセージが表示された
- $
- $ ./sayhello
- Say hello? [y/n] ← (1)のreadに対し[CTRL]+[D]を入力
- bye! ← readできなかったのでwhileを抜けて(6)のメッセージが表示された
- $
- $ ./sayhello
- Say hello? [y/n] ^C ← (1)のreadに対し[CTRL]+[C]を入力
- $ ← スクリプトが即座に終了したので(6)が実行されていない
breakでは処理が中断されてwhile文全体が終了するのに対し、continueは処理を中断して繰り返しの先頭、つまりwhileの行に戻ります。
先ほどの「sayhello」スクリプトで、[Enter]だけ入力した場合はメッセージを出さずに再度入力を待つようにしてみましょう。
[Enter]だけ入力すると、入力内容が空になるので、case文では「"")」で分岐できます(スクリプト内(1))。
- #! /bin/bash
- echo -n "Say hello? [y/n] "
- while read s; do
- case "$s" in
- "y") echo "Hello!";;
- "n") echo "ok"; break;;
- "") continue;; ← (1)入力が[Enter]のみの場合は何もせずにwhileに戻る
- *) echo "input [y] or [n]";;
- esac
- echo -n "again? [y/n] "
- done
- echo "bye!"
このスクリプトを実行すると、次のようになります。[Enter]だけ入力すると、すぐwhileに戻ってreadで入力待ちしている様子が分かります。
- $ ./sayhello
- Say hello? [y/n] ← [Enter]のみ入力
- ← whileの先頭に戻り再度readで入力待ちしているので[Enter]
- y ← whileの先頭に戻り再度readで入力待ちしているのでyと入力して[Enter]
- again? [y/n] n
- ok
- bye!
for文もwhile文も、「繰り返しの処理を行う」という点では共通です。for文と同じような繰り返しをwhile文で書くと次のようになります。
引数を順番に処理する場合は「shift」を使って、引数を1つずつ“ずらし”ます。例えば、引数が「aaa b cc」の場合、1回目のshiftを実行すると引数は「b cc」の2つ、2回目のshiftの後は引数が「cc」の1つになります。shiftを繰り返して引数の数が0になったら、条件がFALSEになり、while文が終了します。
- #! /bin/bash
- while [ $# -gt 0 ]; do #引数の個数が0より大きい間繰り返す
- echo "$1" #1つ目の引数を表示
- shift #引数を1つずらす(シフトする)
- done
- $ chmod +x whileargv
- $ ./whileargv aaa b cc
- aaa
- b
- cc
本連載第33回で取り上げた「for ((i=1; i<=10; i++)) do ~ done」の処理をwhile文で書くと、以下のようになります。
- #! /bin/bash
- i=1 #変数iに「1」をセットする(1)
- while [ $i -le 10 ] #変数iが「10以下」の間繰り返す(2)
- do
- echo "$i" #変数iを表示する
- ((i++)) #変数iを1増やす(3)
- done
このスクリプトでは、whileの前に「i=1」を実行して((1))、whileの条件として「[ $i -le 10 ]」を指定します((2))。「-le」は“lesser or equal”、つまり“以下”という意味です。
続いて、「do ~ done」の中では「((i++))」によって、変数iの値を増やします((3))。この「((i++))」が抜けてしまうと、iがずっと1のままとなり、while文を終了できなくなるので注意してください。スクリプトを終了できなくなった場合は、キーボードで[CTRL]+[C]を入力することで強制的に終了させることができます。
- $ chmod +x whilecount
- $ ./whilecount
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
西村 めぐみ(にしむら めぐみ)
もともとはDOSユーザーで「DOS版UNIX-like tools」を愛用。ソフトハウスに勤務し生産管理のパッケージソフトウェアの開発およびサポート業務を担当、その後ライターになる。著書に『図解でわかるLinux』『らぶらぶLinuxシリーズ』『Accessではじめるデータベース超入門[改訂2版]』『macOSコマンド入門』など。地方自治体の在宅就業支援事業にてMicrosoft Officeの教材作成およびeラーニング指導を担当。会社などの“PCヘルパー”やピンポイント研修なども行っている。
Copyright © ITmedia, Inc. All Rights Reserved.
Linux �ス�ス�ス�ス OSS 鬮ォ�ェ陋滂ソス�ス�コ闕オ譁溷クキ�ケ譎「�ス�ウ驛「�ァ�ス�ュ驛「譎「�ス�ウ驛「�ァ�ス�ー