シェルスクリプト

UNIXメモ / 作成: 2001-11-15


私とシェルスクリプト

はじめ私は、単なる対話的UNIX利用の延長として Cシェルでスクリプトを書いていたのだが、 修士論文を書く直前のクリスマス頃に、 Bシェルスクリプトをマスターして切り替えた。 ある短い数値計算プログラムを、冬休みじゅうの時間を使って、 可能な限り多くのパラメータ値で走らせる必要があったのだ。 それで本格的にシェルスクリプトを勉強する必要があったから、 当時の研究室の先輩に尋ねて、 京大計算機センターの連載記事

誰にでも書ける #! /bin/sh講座 (安岡孝一)
を見て勉強したのだった。 (なお、この連載記事は、 のちに単行本「誰にでも使えるUnix講座」としてまとめられたようだ。)

※ だいぶ後になってから知ったのだが、 Cシェルはコマンドプロンプト用には有効でも スクリプトには全く不向きであり、 シェルスクリプトは基本的にBシェルで書くものだと言われている。 Cシェルがスクリプトに向かない理由については、 「なぜ csh でプログラムを書くのが良くないのか」 (森 大毅 訳)に くわしく書かれている。

当時から私はAWK使いだったから、 Bシェルスクリプト + AWKプログラム で いろんなものを書いた。 FORTRANプログラムを解析するツールまで書きかけたことがある。 その後、21世紀になってからPerlを習得し、現在に至っている。

[ページ冒頭に戻る] [UNIXメモに戻る]


シェルスクリプトを使ってみよう: その1

たとえば、UNIXのcalコマンドは

% cal 12 2001
で2001年12月のカレンダーを出力するが、
% cal 2001 12
とすると、2001年12月とは認識してくれない。 この点を改良したコマンドを、シェルスクリプトで作ってみよう。

まずは、次のような内容のファイルを作る。 ファイル名は、仮にmycalとでもしておこう。

#! /bin/sh

CAL=/usr/bin/cal  # 本物のcalプログラム

if [ $# -eq 2 ]
then
  A=$1; B=$2;
  if [ $A -le 12 ]
  then
    MONTH=$A;  YEAR=$B;
  else
    MONTH=$B;  YEAR=$A;
  fi
  $CAL $MONTH $YEAR
else
  $CAL $@
fi

重要な点は、ファイルのいちばん最初を #! にすることである。 前に空白や空行があってはいけない。 なお、#! の直後の空白は あってもなくても動作するようである。

さて、このファイルを mycal という名前でセーブしたとしよう。 次にすることは、 このファイルの属性を実行可にすることだ:

% chmod u+x mycal
% ls -l mycal
そして、いよいよ実行:
% ./mycal 2001 11
これで2001年11月のカレンダーが表示されれば成功である。

うまくいかない場合、エラーメッセージを見て、 ファイルにおかしいところがないかどうかをさがす。 3行目の /usr/bin/cal の部分は、

% which cal
というコマンドを実行して、 その結果に応じて変更する必要があるかもしれない。 また、イコールの前後に空白があると うまく作動しない。

[ページ冒頭に戻る] [UNIXメモに戻る]


シェルスクリプトを使ってみよう: その2

何か適当なCプログラムなりFORTRANプログラムなりがあるとする:

      implicit none
      real x
      write(0,*) 'input: x = '
      read(*,*)  x              ! 標準入力から読み込む
      write(*,*) x * log(x)     ! 標準出力に書き出す
      stop
      end

上記のプログラムは、 データを標準入力から読み込み、 計算結果を標準出力に書き出すようになっている。 この例ではあまりに単純だが、まあ、たとえば 何か複雑なプログラムをCで書いたとしよう。 そのプログラムは、 やはり何か(たとえばReynolds数などのパラメータ)を標準入力から読み込み、 結果を標準出力に出力するものだとする。 このプログラム(仮にprog01とする)を、 たとえば5つのパラメータで走らせたいとすると、 次のようなシェルスクリプトが役立つかもしれない:

#!/bin/sh

for R in 1 2 3 4 5
do
  PARFILE="reynolds${R}.par"
  DATFILE="reynolds${R}.dat"
  echo $R | awk '{ print 0.1 * $1; }' > $PARFILE  # パラメータの値
  ./prog01 < $PARFILE  > $DATFILE
done

なお、最初の行の #!/bin/sh

#!/bin/sh -vx
とすると、シェルスクリプトの実行の過程をくわしく追うことができる。

[ページ冒頭に戻る] [UNIXメモに戻る]


シェルスクリプト実行機構の応用

じつは、UNIX系のシステムでは

#! /bin/sh
だけでなく さまざまな種類のスクリプトを実行できるようになっている。 たとえば
#! /usr/bin/perl -w
だと Perlスクリプト、
#! /usr/bin/awk -f
だと AWKスクリプトが実行される。

これはどういうことかというと、 たとえば myscript01 というファイルの最初が

#! /bin/sh
となっている場合、UNIX系OSは この行を読みとって
/bin/sh myscript01
を実行するのである。 別の言い方をするなら、 たとえ最初の#!とか実行属性とかがなくても、 スクリプト本体さえ書いてあれば、コマンドラインから
% /bin/sh myscript01
と入力することにより シェルスクリプトの実行は可能である。 最初の#!は、このようなコマンドラインと等価な内容を 自動的に実行するものだと言える。

UNIX系OSでの日本語入力が今よりもさらに不便だったころ、 私は、次のようなスクリプトを作って愛用していた:

#!/usr/bin/tail -1
大信田 丈志

このスクリプトのファイル名はmynameである。 したがって、コマンドラインから

% myname
と入力すると、システムはこれを
/usr/bin/tail -1 myname
と置き換えて実行するので、 私の名前が出力される、というわけだ。 (ちなみに、今は、 mynameを もう少し高機能にしたものを作って愛用している。)


[ページ冒頭に戻る] [UNIXメモに戻る] [ホームページに戻る]