電子計算機及び実習 第 8 回 (12/1)
8 シェルスクリプト
8.1 今日のテーマ
*シェルスクリプト
**今日の提出課題
以下のファイルを添付して,s-suzuki あてに署名をつけて送信せよ.ただし,Subject は 「学籍番号+Dec01」
とせよ.また,メールの本文に添付したファイルの名前を明記すること.
1. kadai8-1.sh 課題8.1で作成されたもの.
2. kadai8-3.sh 課題8.3で作成されたもの.
3. kadai8-5.sh 課題8.5で作成されたもの.
8.2 シェルスクリプト
シェルスクリプトとは,シェルの内部コマンド・UNIXのコマンドを組み合わせて,一連の処理を実行するた めに書かれる一種のプログラムである.
ホームディレクトリのすぐ下に,scriptという名前のディレクトリを作成し,今回作成するシェルスクリプト は全てそのディレクトリに保存するようにすること.
最も基本的なシェルスクリプトはバッチ処理と呼ばれるもので,複数のやりたい命令を,その順番に記述した 手順書である.まず,その例から始めることにしよう41.
test0.sh
¶ ³
#!/usr/bin/bash
# これはシェルスクリプトの例です.
echo "This is my first shell script."
echo --- calendar --- cal
echo ---
µ ´
このシェルスクリプトを実行してみよう.その方法は2つある.
1. % bash ./test0.sh
2. % chmod 700 ./test0.sh
% ./test0.sh
両方の方法を試してみよう.2番目の方法は,test0.shというスクリプトに実行権限を与えて,あたかも一つの 新しいコマンドであるかのようにする方法になっている.UNIXシステムには,このようにして作られたコマン ドもたくさんある.
では,test0.shの内容を見ていこう.第1行目ではそれ以降のスクリプトの本文を処理させるプログラムを指 定する.第2行目以降の#はコメントを表す.echoは文字列を出力するコマンドであり,calはカレンダーを出 力させるコマンドである.第3行目以降は,やらせたい命令を順に出力している.
課題 8.1 現在の時刻とquotaの出力結果を順に出力するシェルスクリプトkadai8-1.shを作り,実行しなさい.
41この講義では,いくつかの理由から,bashによるシェルスクリプトを紹介する.普段ログインシェルとして用いている,tcsh (csh)に よってもシェルスクリプトを記述することが可能だが,その文法はbashのものと大きく異なるので注意を要する.
バッチ処理だけでは,それほど複雑な処理を実行することはできないが,シェルには,変数・条件判定・繰り 返し処理・関数といったプログラム作成に必要な機能が備わっており,アイディア次第でかなり複雑な処理を実 行するシェルスクリプトが作成できる.条件判定と繰り返し処理はまとめて制御構造と呼ばれることもある.以 下では,変数と制御構造について簡単に説明しながら,いくつかのシェルスクリプトを作成してみよう.シェル スクリプトについて,関数の利用等,より高度なことについては,ウェブ上の情報や書籍を参照して欲しい.
変数(シェル変数) 変数はユーザが任意に設定できる.以下の例を入力・実行してみよ.
test1.sh
¶ ³
#!/usr/bin/bash
# 変数の設定,参照の例
comment="計算例"
i=1 j=2
let k=$i+$j let l=$i*$j
echo $comment
echo "i= " $i, "j=" $j, "i+j=" $k, "i*j=" $l
µ ´
実行してみればわかるように,4行目から6行目までで変数の設定を,8行目,9行目で変数の足し算・掛け算 を,11行目,12行目で出力を行っている.変数の値を参照するときには,変数名に $記号を付ければよい.ま た,変数の足し算・掛け算を行うためのbash のコマンドがletである.
条件判定 ある条件が満たされているとき(あるいは満たされていないとき)のみ,ある処理を実行したいこと がしばしばある.たとえば,あるファイルが存在したらそのファイルを消去したい,といったことである.この ためのシェルスクリプトの仕組みが条件判定である.条件判定の書式は,以下のようなものである:
¶ ³
[ 条件式 ]
µ ´
使用できる条件式の構文を表1にまとめておく.以下は具体例である.
test2.sh
¶ ³
#!/usr/bin/bash
echo "val1=?"
read val1
if [ $val1 -gt 5 ] then
echo "$val1 is greater than 5."
else
echo "$val1 is less than or equal to 5."
µfi ´
この例では,read $val1で,標準入力(キーボード)から変数$val1に値(整数値を入れること)を読みこ み,if[ $val1 -gt 5 ] で5より大きいかどうかを判別して,その結果が真なら, $val1 is greater than 5. を出力し,偽なら,$val1 is less than or equal to 5. を出力している.
test3.sh
¶ ³
#!/usr/bin/bash
if [ -e $1 ] then
echo "file $1 exists!"
else
echo "file $1 does not exist!"
µfi ´
この例は,実行時の引数にファイル名を指定し,それが存在するかどうかを判定し,その結果を出力するシェル スクリプトである.変数$n (n=0,1,2,...) にはシェルスクリプト実行時のコマンドライン引数が設定されてて いる.$0にはシェルスクリプトの名前が入り,$1には1番目の引数が入る.if [ -e file name]は,file name というファイルが存在すれば真,存在しなければ偽となり,真の場合thenからelseまでが,偽の場合elseか ら fiまでが実行される.なお,このシェルスクリプトを実行するには,test3.shに実行パーミッションを与え た上で,以下のようにすればよい.
¶ ³
% ./test3.sh file name
µ ´
表1: 条件式の構文
文字列比較 string1 = string2 string1とstring2が同じなら真 string1 != string2 string1とstring2が異なるなら真
-n string stringが空でないなら真
-z string stringが空なら真
整数比較 n1 -eq n2 n1とn2が等しいなら真
n1 -ne n2 n1とn2が異なるなら真
n1 -gt n2 n1がn2より大きいなら真
n1 -ge n2 n1がn2より大きいか等しいなら真
n1 -lt n2 n1がn2より小さいなら真
n1 -le n2 n1がn2より小さいか等しいなら真
ファイルに関する条件 -d file fileが存在し,ディレクトリなら真
-e file fileが存在するなら真
-s file fileが存在し,サイズが0でないなら真
-r file fileが存在し,読み込み可能なら真
-w file fileが存在し,書き込み可能なら真
-x file fileが存在し,実行可能なら真
file1 -nt file2 file1がfile2より新しいなら真 file1 -ot file2 file1がfile2より古いなら真
繰り返し処理 似たような処理を何回も繰り返し実行したいこともよくある.そのための仕組みが繰り返し処理 である.シェルスクリプトの繰り返し処理にはいくつかの構文があるが,ここではwhileを用いるものを紹介し よう.whileを用いた繰り返し処理の構文は以下のようなものである:
¶ ³
while 条件式 do
command ...
µdone ´
これは,条件式が成立する限り,命令commandを実行する.以下,具体例で見ていこう.
test4.sh
¶ ³
#!/usr/bin/bash
i=1
while read str do
echo "$i:$str"
let i=$i+1
µdone ´
この例は,標準入力から入力された文字列に,番号を付けて標準出力に出力している.リダイレクト(<)によっ て,あるテキストファイルを入力すれば,各行に行番号を付して出力するコマンドになる.while read strは変数 strに標準入力から文字列を読み込む作業をあらわし,そが真である限り(読み込める限り),doからdoneの間 の命令が実行されることになる.
なお,このシェルスクリプトを実行するには,test4.shに実行パーミッションを与えた上で,次のようにすれ
ばよい.¶ ³
% ./test4.sh <file name
µ ´
また,file name1に行番号を付したものをfile name2として保存するには,リダイレクト(>)を用いて次のよう にすればよい.
¶ ³
% ./test4.sh <file name1 >file name2
µ ´
次の例は,一定の回数,似通った処理を繰り返すための書式を表している.
test5.sh
¶ ³
#!/usr/bin/bash
i=1 j=0
while [ $i -le $1 ] do
let i=$i+1 let j=$j+$2 echo $j
µdone ´
これの実行例は以下のようなものである:
¶ ³
% ./test5.sh 10 3
µ ´
課題 8.2 test1.shからtest5.shを作成し,それらを実行してみよ.
課題 8.3 以下のような,2のベキを出力するシェルスクリプトを作成せよ.さらに,引数に2つの整数値a, bを 入力すれば,ベキab を出力するシェルスクリプトkadai8-3.sh を作成せよ.
2^1 = 2 2^2 = 4 2^3 = 8
繰り返し処理2 繰り返し処理を行う別の構文を紹介しよう.構文は以下のようなものである.
¶ ³
for 変数 in arg ...
do
command ...
µdone ´
ここで,arg ... は引数の列であり,forはargを変数に代入して命令command を実行し,引数列を全て処理す るとdoneの次の行に抜ける.具体的な例を一つあげておこう.$@は実行時のコマンドライン引数が全て入る.
test6.sh
¶ ³
#!/usr/bin/bash
s=0
for i in $@
do
echo $i let s=$s+$i done
echo $s
µ ´
これの実行例は以下のようなものである:
¶ ³
% ./test6.sh 1 2 3 4
µ ´
課題 8.4 test6.shを作成し,実行してみよ.
簡単な応用として,カレントディレクトリにある全てのTEXファイルの文字コードをEUCコードに変換す るためのシェルスクリプトを作ってみよう.例えば,以下のようにすればいいだろう:
test7.sh
¶ ³
#!/usr/bin/bash
for i in *.tex do
echo $i cp $i $i.org nkf -e $i > $i.e mv $i.e $i
µdone ´
念のため,命令の意味を解説しておく.echo $iでファイルの名前を表示する.cp $i $i.orgでfile name.org の名前でバックアップファイルを作る.nkf -e $i > $i.e で文字コードをEUCコードに変更したものをファ イルfile name.eに保存する.最後にmv $i.e $iで file name.eを元のファイル名に戻す.
課題 8.5 ~/jwww/にある全てのHTMLファイルのパーミッションを644に変更するシェルスクリプトkadai8-5.sh を作成せよ.
課題 8.6 (チャレンジ問題) 以下のような,9×9の掛け算表(九九の表)を出力するシェルスクリプトを作成せ よ.さらに,引数に整数値 nを入力すれば,n×nの掛け算表を出力するシェルスクリプト kadai8-6.sh を作 成せよ.
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18 3 6 9 12 15 18 21 24 27 4 8 12 16 20 24 28 32 36 5 10 15 20 25 30 35 40 45 6 12 18 24 30 36 42 48 54 7 14 21 28 35 42 49 56 63 8 16 24 32 40 48 56 64 72 9 18 27 36 45 54 63 72 81
8.3 本日の課題
以下のファイルを添付して,s-suzuki宛に署名をつけて送信せよ.ただし,Subjectは 「学籍番号+Dec01」と せよ.また,メールの本文に添付したファイルの名前を明記すること.
1. kadai8-1.sh 課題8.1で作成されたもの.
2. kadai8-3.sh 課題8.3で作成されたもの.
3. kadai8-5.sh 課題8.5で作成されたもの.
8.4 次回のテーマ
表計算,数式処理.