今回は、繰り返し処理を中断する際に使用する「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.