2010-03-23
今日は22時からNHKを見よう
密かに楽しみにしている番組、それが「プロフェッショナル -仕事の流儀-」
NHKの毎週火曜日22時から放送されている番組でございます。
そりゃ、サッカーファンであれば絶対見なければいけません。わたくしが中学生の頃(もちろん、まだJリーグなんてありません。。。)、何の番組か忘れましたが、サントスに移籍して間もないカズの映像を見て泣きそうになりました。その頃は、まだジャポネーゼがサッカーなんてできるのか?なんてバカにされていた時代だったのに、カズが実力でプロになってる姿を見て本当に感動しました。そういえば、あの頃って、日本がワールドカップに出るなんて夢にも思えなかった時代。今やワールドカップ出場が当たり前になりつつあるなんて、未だに信じられません。
第4章:リダイレクションによるファイル操作
最初に
第1章から書式や変数などの話しばかりで少し飽きてきましたが、どれもシェルスクリプトを書くためには必要な知識なので何とかがんばっていきたいと思いまする。
第4章は25ページほどで、ファイル操作関連の話しがメイン。やっとこさなんだかプログラムっぽっくなってきました。
ファイルディスクリプタ
ファイルに何か書き込みたいときは、ファイルディスクリプタを使ってファイルアクセスをする。このファイルディスクリプタの番号のうち、0,1,3番は予約されており重要なので覚えるべし。
リダイレクション
通常の入力や出力先を変更することをリダイレクトと言う。リダイレクト記号として「>」「<」を使用する。「>」でファイルに書き込むと、元々のデータがクリアされるので、追記させたい場合は「>>」で行う。
「>」でファイルへリダイレクトすると、正確には1番のディスクリプタを経由するもをファイルへ向けると言う意味になる。エラーはディスプリタ番号2なので、「>」でファイルに向けてもエラーメッセージはファイルに書き込まれない。それを踏まえ、通常のリダイレクトを正確に書くと下記のようになる。
$ cat xxx 1> abc
xxx: No such file or directory
上記のようにすると、エラーメッセージはディスプリタ2番なのでファイルabcに書き込まれず、画面に表示される。
もし、エラーメッセージをファイルに向けるリダイレクトは以下の通り。これを利用すれば、エラーメッセージだけ別のファイルで保存することができる。
$ cat xxx 2> abc
$ cat: xxx: No such file or directory
もし、エラーメッセージと通常の出力結果も1つのファイルに入れたい場合は下記のようにする。
$ cat abc xxx > nnn 2>&1
リダイレクトの記号「>」は、どの場所に書いてもいいが、通常は最後に書くのが普通。もしリダイレクトを複数に書いたりした場合は「左から右」へとなる。例えばあるコマンドの実行結果やエラーメッセージをすべて消し去るときの例は下記のようになる。下記のコマンドだと、コマンドの標準出力を/dev/nullへ書き込み、それから標準エラー(ファイルディスプリタ2)も標準出力(ファイルディスプリタ1)へ行くように書き込んでいる。すでに標準エラーは/dev/nullへ向かっているので、結果、標準エラーも/dev/nullへ行く。
コマンド > /dev/null 2>&1
リダイレクトは、変数でも可能。
STDOUT=/dev/null コマンド > $STDOUT
標準出入力を扱うものとしてパイプ(|)がある。パイプの左側の標準出力をパイプの右側の標準入力にすると言う意味になる。
リダイレクトを使った書き込み
echoコマンドは標準出力にメッセージを出力する。もし、echoコマンドで標準エラーにメッセージを出力したい場合は下記のように書く。
echo "Error messages." 1>&2
もし、3以上のファイルディスプリタへ書き込みしたい場合は
$ echo abcdef 1>&8 $ exec 8> hhh $ echo abcdf 1>&8
ディスプリタは、リダイレクト先のファイルがなければ自動で作ってくれる。
リダイレクトでの読み込み
標準入力も、もちろんリダイレクトできる。キーボードからの入力の代わりにファイルをそのままリダイレクトする。例としては以下の通り。
commmand < file
また、ファイルではなく書いてある文字列とかをそのまま入力することも可能。
command << word
これを「ヒア・ドキュメント」と言う。
ファイルサイズを0にする。
/dev/nullを利用する。エディタで開いて中身を消しても1バイトだけ残ってしまうので。下記のどちらでも大丈夫。
$ cat /dev/null > file $cp /dev/null file
ヒア・ドキュメント(Here Documents)
1つのシェルスクリプトの中に、入力する文字も同時に書いてしまう方法のこと。最初に現れた文字列がもう一度出てきたら、そこまでを入力として認識する。一般的にはENDなどを使用。以下にサンプルをば。最初のEND以降で、2回目のENDまでが標準入力として扱う。
>|sh>
$ cat << END
> This is a
> input data.
> END
||<
上記のとき、変数を標準入力から渡すことも可能。逆に、$DIRなどを変数としてではなく文字列として「$DIR」として扱わせる方法は「\$DIR」と文字列だけをクォートする方法と、下記のようにヒア・ドキュメント全体をクォートする方法がある。後者の方がわかりやすくていい。
$ DIR=document $ cat << \END > This is a > here $DIR. > END This is a here $DIR.
ほかにもクォートする方法として、ENDをシングルクォーテーションで括弧っても同じようになります。('END')
<<の後にハイフン(-)をつけると、ヒア・ドキュメントの部分の先頭のタブ(スペースはダメ)は入力されていないものとして扱う。インデントを無視させたいときに使用する。例えば下記のような書き方をしておけばわかりやすい。
then command <<- END This is a here document. END fi
入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界
- 作者: ブルースブリン,Bruce Blinn,山下哲典
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2003/02
- メディア: 単行本
- 購入: 14人 クリック: 245回
- この商品を含むブログ (60件) を見る
第3章:シェル関数、組み込みコマンド
とりあえず、この第3章ではシェルスクリプトをさらに小さくした1つの固まりのコマンドだと言う程度の理解で十分で、詳しくは第9章でやるらしい。この章では、関数を使う上での注意点を見ていくようだ。
シェル関数
古くからある機能で、よく使われる機能で、一連のコマンドを単に処理するだけ。関数なので戻り値も設定できる。たとえば、ls -lと同じ動作をするシェル関数lslを作成する。
$ lsl(){ > ls -l > }
動作状態による違い
定義した関数を実行すると、それはそのシェルの中で動作する。しかし、関数内でリダイレクトとかをさせると、サブシェルを作って動作する。
関数が、サブシェルで動作するかどうかによって、動作上の違いある。
ディレクトリ
関数終了時のディレクトリが変わる。
関数内でディレクトリを移動する動作を行ったとき、カレントシェルの場合にはその変更内容が残る。しかし、サブシェルの場合には、関数が終了すれば元のディレクトリに戻る。
変数
関数終了時に変数の内容が変わる。
関数内で変数に対して何か処理を行ったとき、カレントシェルの場合にはその変更内容が残る。しかし、サブシェルの場合には関数が終了すれば元の値に戻る。
exitコマンド
シェルが終了するかどうかが変わる。
関数内でexitコマンドを実行したとき、カレントシェルで実行している場合にはそのシェル自体が終了する。しかし、サブシェルの場合にはその関数が終了するだけ。
引数に関する注意
位置パラメータの$0の値が、シェルスクリプトとシェル関数では異なる。シェルスクリプトだと、$0はそのスクリプトの名前が格納されるが、シェル関数ではそのシェル関数を呼び出したシェルが格納される。
シェル関数の場合
$ display(){ > echo $0 $1 $2 $3 > } $ display aaa bbb ccc /bin/bash aaa bbb ccc
シェルスクリプトの場合
$ cat display #! /bin/sh echo $0 $1 $2 $3 $ ./display aaa bbb ccc ./display aaa bbb ccc
変数に関して
シェルスクリプトを1つ作成すると、そのシェルスクリプトで使用させる変数や関数で使用される変数すべてが格納されるテーブルが1つ用意される。1つのシェルスクリプト内の複数の関数で、同じ変数名を使用しているとその変数は同じ変数として処理されてしまう。なので、変数を使用するときは異なる変数名を使うように気をつけるべし。
関数をカレントシェルで動作させる方法
通常、シェルスクリプトに書かれているコマンドは、そのシェルスクリプト内で動作する。決して、そのシェルスクリプトを実行したシェル上で動く訳ではない。しかし、下記のようにシェルスクリプトを実行するとカレントシェルでそのスクリプト内のコマンドを実行することが可能なる。
$ . シェルスクリプト
ちょっとわかりにくいのでソースを見ながら。まず、下記のようなシェルスクリプト書く。
$ cat aaa #! /bin/sh pse() { ps -ax | sort -bn }
下記のようにこのスクリプトファイルを実行しても、pseが実行されるわけではありませんし、その後でpseと実行したって実行されるわけがない。
$ ./aaa $ pse pse; not found
しかし、先ほどのファイルを.(ドットコマンド)を使って実行するとpseをカレントシェルで実行可能になる。
$ . ./aaa $ pse ps -ax | sort -bnの実行結果が表示される
このようなシェルスクリプトは、現在のシェル環境を設定するためのシェルスクリプトとなっている。そこで、このようにシェル環境を設定するためのスクリプトファイルは、ファイルの最後に.shとつけ、さらに、直接実行されないように読み取りのみの権限にしておく。
組み込みコマンド
シェルにはじめから組み込まれているコマンドを組み込みコマンドと言う。個別のコマンドを個別に走らせるより組み込みコマンドを使用したほうが速さやリソース的に効率的らしい。詳しくは後の章で記載されているので、この章では簡単に見ていく。
ヌルコマンド(:)
何もしないが、必ずいつも成功する(真の結果を返す)コマンド。条件判定を必ず真にしたいときによく使用される。たとえば下記に示すようなwhileの場合。下記の例だとヌルコマンドでwhileの条件が必ず真にあるので無限ループになる。
while : do if .... then break if done
ドットコマンド(.)
新しくプロセスを作らずに、現行のシェルのプロセスを使って指定されたファイルを読み込み実行する。その結果、指定されたファイルに記載されている変数や関数が現行のシェルで使えるようになる。
breakコマンド
forやwhileのループから抜けるときに使うコマンド。いくつかのループをまとめて抜けるときには、breakの後に数字をパラメータとして渡すと抜けることができる。
cdコマンド
指定したディレクトリに移動するコマンド。パラメータがなければ、そのユーザのホームディレクトリに移動する。
continueコマンド
forやwhileでいったんループ内の処理を終えて、またループの最初の処理から行わせたいときに使用する。引数を渡すことで、ネストしている何番目のループに戻るかなんてことも可能。
echoコマンド
引数の部分を標準出力に表示するコマンド。特殊コードを出力させるときだけSystem V系とBSD系で異なるらしい。詳しくは12章の汎用性でやる。
evalコマンド
1行に複数のコマンド実行が入っているとき、いっぺんに複数のコマンドを実行してくれる。
execコマンド
execコマンドは、引数のコマンドをカレントシェルのプロセスと置き換えて実行する。
exit
シェルを終了させたいときに使用する。引数を渡すとこのシェルの終了コードを設定することができ、その終了コードは$?に格納される。通常は、正常終了したときには0を格納する。
exportコマンド
パラーメタで指定された変数を、このタイミング以降で実行されたシェルやコマンドで使用できるようにする。通常、変数などは他のシェルからは見えないはずだが、それを見えるようにするのがexportコマンド。詳しくは第5章で。
pwdコマンド
readコマンド
キーボードからの入力をreadの後に指定されたものに格納する。readの後の複数の変数を用意すると、複数の入力値も格納できる。このとき、単語をスペースで区切るように使うスペースなどの区切り文字をIFS(Internal Field Separators)と言う。スペースのほかにタブ改行もIFSにあたる。詳しくは第4章、第8章で。
readonlyコマンド
指定された変数を読み出し専用にする。あんまし使用されないみたい。
returnコマンド
シェル関数から抜けるコマンド。returnの後に指定した番号がその関数の終了コードになる。
setコマンド
シェルのオプションをオンにしたりオフにしたりするコマンド。setで位置パラメータの値を設定すると、下記のように位置パラメータの値が全部クリアされるので注意。
$ cat aaa #! /bin/sh echo $0 $1 $2 $3 $4 set aa bb cc echo $0 $1 $2 $3 $4 $ ./aaa 1 2 3 4 5 ./aaa 1 2 3 4 ./aaa aa bb cc
上記のようにsetで設定し直すことによって、$4の値がリセットされ出力されない。
shiftコマンド
このコマンドは位置パラメータを左にずらす。
testコマンド
ある条件を判定し、条件が真の場合は0、偽の場合は0以外の値を返す。条件として様々な判定をさせることができ、ファイルの読み取りチェックや文字列の長さチェックなどもテスト可能。何が判定できるかあまりに多いので、manを読んだり、サンプルソースで出てきたときにその都度勉強しなおすべし。
trapコマンド
シグナルを受け取ったときに、指定したアクションを実行することが可能。詳しくは第5章で。
typeコマンド
typeコマンドのパラメータにはコマンド名を指定する。パラメータで指定したコマンドの場所などを教えてくれる。サンプルを以下に示す。
$ type date
date is /bin/date
$
umaskコマンド
ファイルを生成するときに、読み書きなどどのモード(権限)で作るかを決定するコマンド。
unsetコマンド
指定した変数や関数を消去するコマンド。ただし、シェルが始めから持っている変数(PATHやIFS)などはunsetできない。
waitコマンド
引数に動作しているプログラムのプロセスIDを渡す。そのプログラムが終わるまで待つ。使い方としては、バックグラウンドで走っている処理が終わるのを待ち、終わったら処理を行いたい場合などに使用する。
入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界
- 作者: ブルースブリン,Bruce Blinn,山下哲典
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2003/02
- メディア: 単行本
- 購入: 14人 クリック: 245回
- この商品を含むブログ (60件) を見る
