はじめに
サーバーエンジニアの研修用に使ったシェルスクリプトの問題集です。
Linuxサーバーを使って、ちょっとしたシェルスクリプトを書きたい方におすすめです。
算術演算について
シェルスクリプトでは算術演算にexprコマンドを使います。
a=`expr 1 + 2`
またbashの機能として
a=$(( 1 + 2 ))
のように $(()) で囲われた部分を算術演算することもできます。
今回はexprコマンドを使用します。
問1
変数を3つ使用し、四則演算の減算を行うスクリプトを作成せよ。
変数は a=10 、 b=5 、cには a-b の結果を格納すること。
回答例
#!/bin/bash
a=10
b=5
c=`expr $a - $b`
echo $c
実行結果
$ ./1.sh
5
解説
変数に値を代入し、exprコマンドを使って計算した結果をcの中に格納して出力します。
変数名の先頭に$(ダラー)を付けることで変数に格納している値を使用することができます。
問2
変数を使用し、キーボードから入力した文字列を表示させるスクリプトを作成せよ。
入力した文字を格納する変数aを使用すること
回答例
#!/bin/bash
echo "入力"
read a
echo "出力"
echo $a
実行結果
$ ./2.sh
入力
あいうえお
出力
あいうえお
解説
readコマンドは標準入力からデータを読み込みます。ここでは読み込んだデータをaに格納し、echoコマンドを使って出力します。
問3
現在の日時と時間を表示するスクリプトを作成せよ。
日、月、年、時間の順で表示させること。
日、月、年、時間の間には、「、」を表示させること。
回答例
#!/bin/bash
date "+%d日、%m月、%Y年、時刻%T"
実行結果
$ ./3.sh
26日、07月、2011年、時刻11:18:48
解説
時刻を表示するにはdateコマンドを使います。dateコマンドに+から始まる引数を渡すことで指定したフォーマットで出力することができます。
%を使って指定したフィールドの値を取得することができます。
%d 月内通算日数 (01..31)
%m 月 (01..12)
%Y 年 (1970...)
%T 時刻、24 時間 (hh:mm:ss)
dateコマンドの詳しい使い方はman dateコマンドで見ることができます。
問4
if文を使用し、実行時点の「午前、午後」の判別を行うスクリプトを作成せよ。
回答例
#!/bin/bash
hour=`date "+%H"`
# 12より小さい時の処理
if [ $hour -lt "12" ]; then
echo "午前です"
# 12以上の時の処理
elif [ $hour -ge "12" ]; then
echo "午後です"
fi
実行結果
$ date
2011年 7月 25日 月曜日 11:00:19 JST
$ ./4.sh
午前です
解説
dateコマンドの引数で ”+%H” を渡します。
%H 時 (00..23)
変数hourには現在の時刻00~23が入ります。条件式でhourが12より小さければ「午前です」、hourが12以上であれば「午後です」と出力します。
問5
for文を使用し、1週間の間で、何日忙しいか表示させるスクリプトを作成せよ。
月曜日から日曜日にかけてyes / no で入力できるようにすること。
回答例
#!/bin/bash
# 忙しいかった日をカウントする変数
busyday=0
for week in 月 火 水 木 金 土 日; do
echo "$week曜日は忙しかったですか?(yes/no)"
read busy
case $busy in
yes) busyday=`expr $busyday + 1`;;
no) continue;;
esac
done
echo "$busyday日、忙しい日がありました。"
実行結果
$ ./5.sh
月曜日は忙しかったですか?(yes/no)
yes
火曜日は忙しかったですか?(yes/no)
no
水曜日は忙しかったですか?(yes/no)
yes
木曜日は忙しかったですか?(yes/no)
no
金曜日は忙しかったですか?(yes/no)
no
土曜日は忙しかったですか?(yes/no)
no
日曜日は忙しかったですか?(yes/no)
yes
3日、忙しい日がありました。
解説
まずカウント用変数busydayを用意します。次にfor文のリストに月~日曜日までの7つの値を用意します。for文はリストの値をweek変数に格納してリストが終わるまで実行します。
readコマンドでyes / noの入力をbusy変数に格納します。
次にcase文を使ってbusy変数がyesの場合はbusydayをインクリメントして、noの場合はcontinueで処理を続けます。
問6
if文を使用し、入力された値を100未満、100以上1000未満、1000以上かを判断するスクリプトを作成せよ。
「100未満です」、「100以上1000未満です」、「1000以上です」のいずれかを返すこと。
回答例
#!/bin/bash
echo "数値を入力"
read num
if [ $num -lt "100" ]; then
echo "100未満です"
elif [ $num -ge "100" ] && [ $num -lt "1000" ]; then
echo "100以上1000未満です"
elif [ $num -ge "1000" ]; then
echo "1000以上です"
fi
実行結果
$ ./6.sh
数値を入力
99
100未満です
$ ./6.sh
数値を入力
100
100以上1000未満です
$ ./6.sh
数値を入力
999
100以上1000未満です
$ ./6.sh
数値を入力
1000
1000以上です
解説
変数numに入力された値が条件式に当てはまるものを出力します。
# numが100以下で未満であれば実行される
if [ $num -lt "100" ];
# numが100以上 かつ numが1000未満であれば実行される
elif [ $num -ge "100" ] && [ $num -lt "1000" ];
# numが1000以上であれば実行される
elif [ $num -ge "1000" ];
問7
while文を使用し、入力された値をデクリメントしながら表示し、5になった時点で終了するスクリプトを作成せよ。「5」未満の入力はエラーメッセージを表示すること。
回答例
#!/bin/bash
echo "5以上の数値を入力してください"
read num
if [ $num -ge "5" ]; then
echo "出力"
while [ $num -ge "5" ]; do
echo "$num"
num=`expr $num - 1`
done
echo "終わり"
else
echo "5以上の数値ではありません。"
fi
実行結果
$ ./7.sh
5以上の数値を入力してください
4
5以上の数値ではありません。
$ ./7.sh
5以上の数値を入力してください
15
出力
15
14
13
12
11
10
9
8
7
6
5
終わり
解説
変数numに格納された値が5以上であれば処理を実行します。
while文でnumの値が5より小さくなるまでnumの値を出力しながらデクリメントしていきます。
numが5より小さくなれば処理を終了します。
問8
until文を使用し、5から1まで順に表示していくスクリプトを作成せよ。
回答例
#!/bin/bash
count=5
until [ $count -eq "0" ]; do
echo $count
count=`expr $count - 1`
done
実行結果
$ ./8.sh
5
4
3
2
1
解説
まず変数countに5を代入します。until文では条件が成立しない間ループを繰り返します。なのでcount変数が0になるまでcount変数を出力しながらデクリメントしていきます。
countが0になれば条件が成立するのでループを終了します。
問9
変数numを乱数で宣言し、入力した値が同じになるまで繰り返すスクリプトを作成せよ。
while文を使用すること。
入力値が乱数より大きいか小さいかを表示させること
回答例
#!/bin/bash
num=`expr $RANDOM % 10`
echo "数当てゲーム"
while :
do
echo "0~9の数値を入力してください"
read inputNumber
if [ $inputNumber -eq $num ]; then
echo "正解!$numでした"
break
elif [ $inputNumber -gt $num ]; then
echo "もっと小さい"
elif [ $inputNumber -lt $num ]; then
echo "もっと大きい"
fi
done
実行結果
$ ./9.sh
数当てゲーム
0~9の数値を入力してください
4
もっと大きい
0~9の数値を入力してください
7
もっと小さい
0~9の数値を入力してください
6
もっと小さい
0~9の数値を入力してください
5
正解!5でした
解説
bashではRANDOMという乱数を生成する変数が用意されています。RANDOMは0から32767のランダムな値を生成します。変数numにはRANDOMで取得した値を10で割った余りが格納されます。なのでnumには0~9までの値が格納されます。
この例では正解するまでwhileで処理を繰り返し、正解するとbreakでループを抜けます。
whileで無限にループさせたいときには
while :
do
done
while [ 1 ]
do
done
などと書きます。
変数inputNumber に0から9までの入力された値を読み込みます。
# inputNumber とnumが一致した場合
if [ $ inputNumber -eq $num ];
inputNumber とnumが一致した場合は”正解!$numでした”と出力した後、breakしてループを抜けます。
# inputNumber がnumより大きい場合
elif [ $ inputNumber -gt $num ];
inputNumber がnumより大きい場合は”もっと小さい”と出力します。
# inputNumber がnumより小さい場合
elif [ $ inputNumber -lt $num ];
inputNumber がnumより小さい場合は”もっと大きい”と出力します。
問10
四則演算をメニュー形式で行えるスクリプトを作成せよ。
回答例
#!/bin/bash
while :
do
echo "四則演算 1)加算 2)減算 3)乗算 4)除算 5)終了"
read calc
case $calc in
1)
echo "加算を始めます"
echo "最初の値を入力"
read num1
echo "次の値を入力"
read num2
answer=`expr $num1 + $num2`
echo "$num1 + $num2 = $answer です"
;;
2)
echo "減算を始めます"
echo "最初の値を入力"
read num1
echo "次の値を入力"
read num2
answer=`expr $num1 - $num2`
echo "$num1 - $num2 = $answer です"
;;
3)
echo "乗算を始めます"
echo "最初の値を入力"
read num1
echo "次の値を入力"
read num2
answer=`expr $num1 '*' $num2`
echo "$num1 x $num2 = $answer です"
;;
4)
echo "除算を始めます"
echo "最初の値を入力"
read num1
echo "次の値を入力"
read num2
answer=`expr $num1 '/' $num2`
echo "$num1 / $num2 = $answer です"
;;
5) break;;
esac
done
echo "終了しました"
実行結果
$ ./11.sh
四則演算 1)加算 2)減算 3)乗算 4)除算 5)終了
1
加算を始めます
最初の値を入力
3
次の値を入力
4
3 + 4 = 7 です
四則演算 1)加算 2)減算 3)乗算 4)除算 5)終了
2
減算を始めます
最初の値を入力
10
次の値を入力
3
10 - 3 = 7 です
四則演算 1)加算 2)減算 3)乗算 4)除算 5)終了
3
乗算を始めます
最初の値を入力
5
次の値を入力
5
5 x 5 = 25 です
四則演算 1)加算 2)減算 3)乗算 4)除算 5)終了
4
除算を始めます
最初の値を入力
10
次の値を入力
2
10 / 2 = 5 です
四則演算 1)加算 2)減算 3)乗算 4)除算 5)終了
5
終了しました
解説
メニュー形式で計算方法を選べるようにします。calc変数に入力された値を条件に処理をcase文によって分けています。
計算方法としてはreadコマンドにてnum1、num2の値を読み込み、exprコマンドにて計算した結果をanswer変数に代入し出力しています。
注意しなければならないのは乗算と、除算を意味する*(乗算) / (除算)は特殊文字として扱われるのでシングルクォートで囲って文字をエスケープしなければなりません。
乗算 answer=`expr $num1 '*' $num2`
除算 answer=`expr $num1 '/' $num2`
この実行例ではメニューで5が選択されるまでwhile文にて処理を繰り返します。
以上で終わります。