next up previous contents
Next: while文 Up: ループ制御 Previous: ループ制御

for文

 

一組のコマンドを指定された回数だけ実行するのに使われ、 一般書式は次のようになっています。

for val in arg1 arg2 argn
do
  commands
   
done
do doneに囲まれたコマンド群がループの本体で、 これらのコマンド群は inの後ろに並べられた引数の数だけ繰返し実行されます。 このループが実行されると最初に arg1の内容が valに、次に arg2 の内容が val、と順次が参照されながら inに続くリストの中身が 空になるまでループ処理が継続します。つまり、 inの後ろに n個の引数があった ならば n回ループが実行されることになります。 inに続く引数に *, ?, [ ]など のメタ文字が含まれる場合にはシェルにより展開されてから forループが実行されます。

シェル変数 $* はスクリプトに渡されたすべての引数に対応するために for文と 組み合わせて使うことができます。しかし、実際の使用に当っては少し注意が必要です。 次に示すものはコマンドラインに入力された引数を1行に1個づつ表示させるものです が、時として期待を裏切ります。

echo "Number of arguments: $#"
for i in $*
do
  echo $i
done
このスクリプトをfor.shとして実行してみましょう。まずは、
$ for.sh A B C
Number of argumets: 3
A
B
C
これは正常です。ではつぎにAとBを引用符で囲んでみましょう。
$ for.sh 'A B' C
Number of argumets: 2
A
B
C
さて、不思議なことが起こるものです。単一引用符は文字列をシェルから保 護しますから引数は2つ。事実、与えられた引数の数を示すシェル変数 $# は 間違いなく2と表示されています。なのになぜか3行に出力されてしまいました。

種明かしはこうです。'A B' はシェルから保護されて1つの引数として スクリプトに渡されます。しかし、保護されるのはコマンドラインでのことであり、 引数としてスクリプトに渡った時には単一引用符が外れています。ですから、 for文で $* が展開された時、 in以降のリストにはAとBを1つにしている単一引 用符がありませんので、

for i in A B C
となってしまい、ループは3回実行されることになります。 これを回避するために for文には in以降のリストを持たない特別な記述が許されてい ます。for.sh2行目の in以降を省略し、
echo "Number of arguments: $#"
for i
do
  echo $i
done
としたものです。これで試してみると
$ for.sh 'A B' C
Number of argumets: 2
A B
C
となるはずです。さらに、特殊なシェル変数 $@ を使うもの1つの方法です。 シェル変数 $* はコマンドラインでの引用符が外された状態の引数を $1, $2, $3として持っています。この $* の代わりに "$@" を使う と "$1", "$2", "$3" として置き換えられるために $* で のような不都合は起こりません。 ただし、二重引用符で囲み "$@" としなければ $* とまったく同じよう に展開されてしまいます。



Riichiro Saito
1995年08月29日(火) 11時41分26秒 JST