|
1から100までの数値を順に変数iに入れて順に出力する場合Cシェルでは、このように書くことができます。
#!/bin/csh -f
@ i = 1
while ($i <= 100)
echo $i
@ i ++
end
このスクリプトはどこにでもある例文なのですが 問題はBourneシェルで書くにはどうすれば良いかなのです。Bourneシェルで書くとこうなります。
#!/bin/sh
i=1
while [ $i -le 100 ]; do
echo $i
i=`expr $i + 1`
done
Bourne シェルは、算術演算の機能を自分では持っていません。ここでは、それを実現するために、testとexprという外部コマンドを呼び出しています。testの方は見つけにくいかもしれませんね。これは3行目の
`[' です。`[' は testコマンドの省略形です。ループ変数が100以下かどうかの判定はtestコマンドに、ループ変数のインクリメントは
exprコマンドに肩代わりしてもらっているというわけです。
しかし細かな部分で注意が必要です。以下にまとめました。
2行目のi=1は、スペースを入れて書いてはいけない。
3行目のwhile, [, $i, -le, 100 の後のスペースは入れて書かなければならない。
5行目のi=`は、スペースを入れて書いてはならない。 exprの後の3つの要素間のスペースは入れて書かなければならない。
2行目のiに、 `$' を付けてはならない。 5行目の1番目のiに `$' を付けてはならない。
5行目の$iの `$' を忘れてはならない。
このような問題は、何もBourneシェルだけのものではありません。上に挙げたCシェルスクリプトは、見やすさの上では若干有利ですが、
@ i = 1などのスペースはやはり省略できません。
ではforを使うとどんな記述になるのでしょうか。一般
に使われるシェルのforは以下の様なものですよね。
#!/bin/sh
for i in 1 2 3 4 5; do
echo 今 $i 回目
done
しかし in 以降の数値はひとつひとつの動作に対して記述しなければなりません。
ではforでのループを考えていきましょう。その前に次のPerlスクリプトを見てください。
#!/usr/bin/perl
for($i=1; $i<=5; $i++) {
print "今 $i 回目\n";
}
Perlのことを全く知らなくても、このコードは簡単に理解できるでしょう。
C との違いは、main()がないこと、変数の宣言がないこと、変数 の頭に$が付いていることくらいでしょうか。え、printfじゃないのかって?
大丈夫、ちゃんと printfも用意されています。
このスクリプトをloop5という名前で保存してからコマンドラインでperl
loop5と入力すると、結果が見られます。実行属性を与えてから単にloop5としても同じです。
ここで、もう一つ覚えてください。それは、Perlはスクリプトを直接引数に書くことができる、ということです。このためには、-eというオプションを使います。上述したPerlスクリプトを実行するのと同じことを、コマンドラインから次のように指示できます。
perl -e 'for($i=1;$i<=5;$i++){print"今
$i 回目\n"}'
Perlは自由なフォーマットでプログラムが書けますから、このように1行で書いたりスペースや改行を省いたりしても問題ありません。
さて、本題に戻りましょう。Bourneシェルのfor文では、制御変数の値を
inの後ろに並べて書くのでしたね。1から100までの数字を手で入力するのはとても大変です。そこで、この部分はPerlにやってもらうことにしましょう。次が最終形です。
#!/bin/sh
for i in `perl -e 'for($j=1;$j<=100;$j++){print "$j "}'`;
do
echo $i
done
このシェルスクリプトの最大のミソは、バッククオート(`)です。一対のバッ
ククオートで囲まれたコマンド列はシェルによっていったん実行され、その結果
得られる出力がこの部分と置き換わります。つまり、このスクリプトの意味
するところは次のものと全く同じになります。
(補足: 最終形に出てきたPerlの1行スクリプトでは、制御変数に
$iではなく$jを使っています。これは、シェル変数iと見間違えないように変えておいただけで、
$iにしても問題なく動作します。)
|