このページでは、具体的な作業を通してシェルスクリプトの作成を練習していき ます。
を実現するためのシェルスクリプトを作ります。 段階的に説明していきますので、最初から順を追って演習してみましょう。
作業用ファイルの作成
「シェルスクリプトでの制御文」では、 同じ処理を繰り返すために、whileを使用しました。ここで、このwhileを 使用した処理から始めます。 「emacs」で「script1-1.sh」というファイルを作成します。下記の内容を 記述してください。
#!/bin/bash i=1 while [ "$i" -le 100 ] do touch temp${i}.txt i=`expr $i + 1` done
保存したら、chmodを使用して「script1-1.sh」を 実行形式に変更します。その後に、下記の赤字で表示されているように入力して 実行してみましょう。
bash-2.05$ ./script1-1.sh bash-2.05$ ls temp* temp1.txt temp24.txt temp4.txt temp55.txt temp70.txt temp86.txt temp10.txt temp25.txt temp40.txt temp56.txt temp71.txt temp87.txt temp100.txt temp26.txt temp41.txt temp57.txt temp72.txt temp88.txt temp11.txt temp27.txt temp42.txt temp58.txt temp73.txt temp89.txt temp12.txt temp28.txt temp43.txt temp59.txt temp74.txt temp9.txt temp13.txt temp29.txt temp44.txt temp6.txt temp75.txt temp90.txt temp14.txt temp3.txt temp45.txt temp60.txt temp76.txt temp91.txt temp15.txt temp30.txt temp46.txt temp61.txt temp77.txt temp92.txt temp16.txt temp31.txt temp47.txt temp62.txt temp78.txt temp93.txt temp17.txt temp32.txt temp48.txt temp63.txt temp79.txt temp94.txt temp18.txt temp33.txt temp49.txt temp64.txt temp8.txt temp95.txt temp19.txt temp34.txt temp5.txt temp65.txt temp80.txt temp96.txt temp2.txt temp35.txt temp50.txt temp66.txt temp81.txt temp97.txt temp20.txt temp36.txt temp51.txt temp67.txt temp82.txt temp98.txt temp21.txt temp37.txt temp52.txt temp68.txt temp83.txt temp99.txt temp22.txt temp38.txt temp53.txt temp69.txt temp84.txt temp23.txt temp39.txt temp54.txt temp7.txt temp85.txt
上記の結果でわかったように「script1-1.sh」はtemp?.txt(またはtemp??.txt) という名前のファイルを生成するスクリプトです。 touchコマンドで 存在しないファイル名を続いて入力すると、中身が空のファイルを生成します。
この100個のファイル名を見ると、
temp1.txt temp10.txt temp100.txt
のように、1や10、100などの数字によって桁数が変わるため、ファイル名の長さ も変わっています。この数字を001や010などに統一して、ファイル名の長さを 揃えるという作業に取り組みます。ここで行う作業はいろいろと応用が利きます 。
名前変更用スクリプト
それでは、ファイル名を変更するためのスクリプトを作ります。 「script1-2.sh」というファイルに、下記の内容を記述してください。
#!/bin/bash i=1 while [ "$i" -le 100 ] do if [ "$i" -lt 10 ] then num=00${i} elif [ "$i" -lt 100 ] then num=0${i} else num=${i} fi mv temp${i}.txt temp${num}.txt i=`expr $i + 1` done
保存したら、chmodを使用して「script1-2.sh」を 実行形式に変更します。その後に、下記の赤字で表示されているように入力して 実行してみましょう。
bash-2.05$ ./script1-2.sh bash-2.05$ ls temp* temp001.txt temp022.txt temp043.txt temp064.txt temp085.txt temp002.txt temp023.txt temp044.txt temp065.txt temp086.txt temp003.txt temp024.txt temp045.txt temp066.txt temp087.txt temp004.txt temp025.txt temp046.txt temp067.txt temp088.txt temp005.txt temp026.txt temp047.txt temp068.txt temp089.txt temp006.txt temp027.txt temp048.txt temp069.txt temp090.txt temp007.txt temp028.txt temp049.txt temp070.txt temp091.txt temp008.txt temp029.txt temp050.txt temp071.txt temp092.txt temp009.txt temp030.txt temp051.txt temp072.txt temp093.txt temp010.txt temp031.txt temp052.txt temp073.txt temp094.txt temp011.txt temp032.txt temp053.txt temp074.txt temp095.txt temp012.txt temp033.txt temp054.txt temp075.txt temp096.txt temp013.txt temp034.txt temp055.txt temp076.txt temp097.txt temp014.txt temp035.txt temp056.txt temp077.txt temp098.txt temp015.txt temp036.txt temp057.txt temp078.txt temp099.txt temp016.txt temp037.txt temp058.txt temp079.txt temp100.txt temp017.txt temp038.txt temp059.txt temp080.txt temp018.txt temp039.txt temp060.txt temp081.txt temp019.txt temp040.txt temp061.txt temp082.txt temp020.txt temp041.txt temp062.txt temp083.txt temp021.txt temp042.txt temp063.txt temp084.txt
上記の結果に示されているように、「script1-2.sh」によって長さが そろったファイル名に一気に変換できたことがわかりました。
while
上記の例題と同様に、ここでもwhileを使用した処理から始めます。 「emacs」で「script2.sh」というファイルを作成します。下記の内容を 記述してください。
#!/bin/bash while [ "$1" != "" ] do echo $1 shift done
保存したら、chmodを使用して「script2.sh」を 実行形式に変更します。その後に、下記の赤字で表示されているように入力して 実行してみましょう。
bash-2.05$ ./script2.sh aaa bbbbb cc d e aaa bbbbb cc d e
スクリプトの中身を見ると、
#!/bin/bash while [ "$1" != "" ] <- $1(1番目の引数)が空白でない間、 do 処理を繰り返す echo $1 <- $1の表示 shift <- 引数のシフト($2が$1へ代入される) done
ということで、すべての引数が表示されることになります。
cutコマンドによる文字列の抽出
これまでに、引数の概念に加えてwhile文を利用した処理を説明してきました。 今度はcutコマンドによる文字列の抽出に挑戦します。 引数でファイル名を指定して処理をさせ別のファイルに 出力させるのですが、出力先のファイル名は、元のファイル名を利用した名前に するために必要な処理です。
上記で作成した「script2.sh」を開き、赤く表示された部分を追加して、 保存してください。
#!/bin/bash while [ "$1" != "" ] do name=`echo $1 | cut -f1 -d'.'` echo $1, $name shift done
これは引数の文字列を . を境に分割し (cutコマンド)、 . より前の 文字列をnameという変数に入れています。 cutコマンドについては、 こちらのページに使用例が紹介されています。
保存したら、下記の赤字で表示されているように入力して 実行してみましょう。
bash-2.05$ ./script2.sh sample1.html sample2.html sample3.html sample1.html, sample1 sample2.html, sample2 sample3.html, sample3
出力結果を見ると、引数と . までの文字列とが表示されていることがわかります。
上記の結果をふまえて、下記の赤い表示部分を追加修正して、 同じ「script2.sh」というファイル名で保存しましょう。 これまでとの違いは、抽出した文字列を元に、文字コード変換後の ファイル名を設定して表示させているだけのことです。
#!/bin/bash while [ "$1" != "" ] do name=`echo $1 | cut -f1 -d'.'` fname=${name}_e.html echo $1, $fname shift done
(出力結果) bash-2.05$ ./script2.sh sample1.html sample2.html sample3.html sample1.html, sample1_e.html sample2.html, sample2_e.html sample3.html, sample3_e.html
nkfによる文字コードの変換
ここで、今回のシェルスクリプト作成の中心であるnkfを説明します。 nkfにより元々のファイルの日本語の文字コードが何であっても、任意の文字 コードへ変換できます。基本的な使い方は、
EUC-JPへ出力する場合 :nkf -e ファイル名 JISへ出力する場合 :nkf -j ファイル名 Shift_JISへ出力する場合:nkf -s ファイル名
です。しかし、上記の通りに実行すると、文字コードが変換された結果が 標準出力(スクリーン)に表示されてしまうだけです。今回は変換結果を 別のファイルに保存するという目的があります。ですので、 >を併用して、出力結果を ファイルに保存させるようにします。
EUC-JPへ出力する場合: nkf -e 元のファイル名 > 変換後のファイル名 JISへ出力する場合: nkf -j 元のファイル名 > 変換後のファイル名 Shift_JISへ出力する場合: nkf -s 元のファイル名 > 変換後のファイル名
今回、ここではbashの使用を念頭に置いていますが、csh、tcshの場合、変換後 のファイル名が既に存在しているファイルと同一名であれば、上書きしない 設定にしてあることがよくあります(~/.cshrcの中に 「set noclobber」とあれば、上書きされないようになっています)。 ですので、強制的に上書きして出力する場合には、 >!を使用します。この後では、 >を使うものとします。
それではこれまで作成してきた「script2.sh」というファイルに、下記の 赤い部分を追加、修正しましょう。
#!/bin/bash while [ "$1" != "" ] do name=`echo $1 | cut -f1 -d'.'` fname=${name}_e.html nkf -e $1 > $fname shift done
これを実行する前に、変換すべきHTML文書を自分のディレクトリに保存します。 下記のWebページを「sample1.html」「sample2.html」「sample3.html」 という名前で保存してください。
ここで新たに修正した「script2.sh」の実行は今しばらく待ってください。
変換後のファイルの移動、パーミッションの変更
最後に、文字コード変換後のHTML文書をWebブラウザ上で確認するために、 public_htmlディレクトリへ移動し、その際にパーミッションを変更する 作業を同時に行います。先の「script2.sh」に、下記のように修正を加え ましょう。
#!/bin/bash while [ "$1" != "" ] do name=`echo $1 | cut -f1 -d'.'` fname=${name}_e.html nkf -e $1 > $fname mv $fname ~/public_html chmod 604 ~/public_html/$fname shift done
それでは下記のように実行してみてください。
bash-2.05$ ./script2.sh sample1.html sample2.html sample3.html
この結果を確認するには、Webブラウザ上で、
などのURLで閲覧し、その際の文字コードを、メニューバーの「表示」-> 「エンコード」などで確認してみましょう。実行の結果、EUC-JPの 文字コードになっているはずです。
上記の「sample1.html」「sample2.html」「sample3.html」のHTML文書に 含まれるタグをすべて除去して、「sample1.txt」のような名前のテキストファ イルとして出力するようなシェルスクリプトを作成したい。
その手順は、上記の「日本語文字コードの変換処理」とほぼ同じである。あらま しを書くと、
である。タグを除去するには、
% sed -e "s/<[^>]*>//g" ファイル名
と実行する。出力結果は標準出力なので、ファイルに出力する場合、
% sed -e "s/<[^>]*>//g" ファイル名 > タグを除去したファイル名
と指定すればいい。ただし、タグの開始と終了(<と>)が同一行に存在し ているという前提が必要となる。詳細は、sedコマンドのページを参照されたい。
上記のヒントにしたがって、自分自身でHTMLタグを除去して、別名で保存するよ うなシェルスクリプトを作成せよ。