シェルスクリプトに挑戦しよう(14)制御構文[その6]――while/untilによる繰り返し処理:“応用力”をつけるためのLinux再入門(34)
シェルスクリプトでは、条件が成り立っている間の繰り返し処理には「while文」を、条件が成り立っていない間の繰り返し処理には「until文」を使用します。今回は、while/untilによる繰り返し処理を解説します。
while/until文はどのような場合に使用するのか?
シェルスクリプトで「while」は、「条件が成り立っている間、処理を繰り返す」というときに使います。
「until」はwhileの逆で、「条件が成り立たない間(条件が成り立つまでの間)、処理を繰り返す」というときに使用します。
whileを使った繰り返し文は「while文」、untilを使った繰り返し文は「until文」、あるいは両者をまとめて「while文」と呼ぶことがあります。
whileとuntilは、コマンドラインで使うこともできます。whileの使用例については、連載「Linux基本コマンドTips」の第219回で取り上げています。
なお、繰り返しの処理には「for」を使うこともあります。「for文」は「全てのファイルに対し同じ処理を行う」「同じ処理を10回繰り返す」のように、処理対象や回数が決まっている場合に便利です。forによる繰り返し処理については、本連載の第31回を参照してください。
●whileの基礎構文
while文は、「while 条件 do 〜 done」のように記述します。条件が成り立っている間、doとdoneの間に書かれた処理を繰り返します。
while 条件 do コマンド done
条件は、if文と同様に、「[〜]」を使ったり、コマンドを記述したりします。例えば、以下はreadコマンドでキーボードからの入力を受け取り、「"0"が入力されたら終了」という条件のスクリプトです。
#! /bin/bash str="-1" #変数strに「0」以外の値を入れておく(※省略可能) while [ $str != "0" ] #変数strが「0」でない間繰り返す do read -p "input? > " str #「input? > 」と表示し入力を待つ。入力内容を変数strにセットする echo your input is $str done
$ chmod +x whiletest $ ./whiletest input? > abc ← 「abc」と入力して[Enter] your input is abc input? > 1 ← 「1」と入力して[Enter] your input is 1 input? > 0 ← 「0」と入力して[Enter] your input is 0 $ ← 「0」が入力されたので終了
●untilの基礎構文
until文は、「until 条件 do 〜 done」のように記述します。条件が成り立っていない間、doとdoneの間に書かれた処理を繰り返します。
until 条件 do コマンド done
先ほどのwhileを使ったスクリプト(whiletest)と全く同じ内容をuntilで書くと、次のようになります。条件部分が「0と一致」に変わっている点に注目してください。
#! /bin/bash str="-1" #変数strに「0」以外の値を入れておく(※省略可能) until [ $str = "0" ] #変数strが「0」でない間繰り返す do read -p "input? > " str #「input? > 」と表示し入力を待つ。入力内容を変数strにセットする echo your input is $str done
$ chmod +x untiltest $ ./untiltest input? > abc ← 「abc」と入力して[Enter] your input is abc input? > 1 ← 「1」と入力して[Enter] your input is 1 input? > 0 ← 「0」と入力して[Enter] your input is 0 $ ← 「0」が入力されたので終了
●コマンドを繰り返し実行する
「while コマンド」で、コマンド実行が成功している間、ずっと処理を繰り返すことができます。以下は、「標準入力から文字列を1行ずつ読み込んで、行番号付きで表示する」というスクリプトです。「while readコマンド」で処理を繰り返しています。
#! /bin/bash i=0 #変数iに「0」をセット(変数iは行番号を表示するのに使用) while read str #readコマンドで読み込んだ内容を変数strにセット do let i++ #変数iの値を「1」増やす echo "$i:$str" #「行番号:入力内容」を表示 done
なお、doの後の「let i++」は変数「i」の値を「1」増やす、という意味です。for文で使用する算術式と同じで、「((i++))」と書くことも可能です。
「while read str」によって、「readコマンドが成功している間、ずっと処理が繰り返される」ということになります。
キーボードから入力する場合は、[Enter]ごとに処理が実行されます。処理を終了したい場合は、“ファイルの終了(EOF、End Of File)”という意味の[CTRL]+[D]を入力するか、[CTRL]+[C]でスクリプトそのものの実行を終了します。
$ chmod +x linenumber $ ./linenumber aaa ← 「aaa」と入力して[Enter] 1:aaa bbb ← 「bbb」と入力して[Enter] 2:bbb ← 「bbb」を読み込んだので表示 ^C ← [CTRL]+[C]を入力 $ ← スクリプトが終了した
readコマンドは標準入力から文字列を読み取るので、リダイレクトまたはパイプを使用すればファイルを読み込んで表示することができます。この場合、ファイルの終了(EOF)でreadコマンドが“失敗”したことになり、while文が終了します。
$ ./linenumber < /etc/shells ← ファイルをリダイレクトする(「cat /etc/shells | ./linenumber」でも同じことができる) $ ./linenumber < /etc/shells 1:/bin/sh 2:/bin/bash 3:/sbin/nologin 4:/usr/bin/sh 5:/usr/bin/bash 6:/usr/sbin/nologin 7:/bin/tcsh 8:/bin/csh 9:/bin/zsh $
●while文の改行ルール
while文では、「do」の前と「done」の前に改行が必要です。if文同様、「;」記号で改行をなくすことができます。
先ほどのスクリプト「linenumber」を書き換えると、次のようになります。どちらも内容は同じです。
#! /bin/bash i=0 while read str; do let i++ echo "$i:$str" done
#! /bin/bash i=0; while read str; do let i++; echo "$i:$str"; done
次回もwhile文と、繰り返し処理を中断させる際に使用する「break」「continue」を取り上げます。
筆者紹介
西村 めぐみ(にしむら めぐみ)
もともとはDOSユーザーで「DOS版UNIX-like tools」を愛用。ソフトハウスに勤務し生産管理のパッケージソフトウェアの開発およびサポート業務を担当、その後ライターになる。著書に『図解でわかるLinux』『らぶらぶLinuxシリーズ』『Accessではじめるデータベース超入門[改訂2版]』『macOSコマンド入門』など。地方自治体の在宅就業支援事業にてMicrosoft Officeの教材作成およびeラーニング指導を担当。会社などの“PCヘルパー”やピンポイント研修なども行っている。
Copyright © ITmedia, Inc. All Rights Reserved.