連載 シェルスクリプト・ステップ・バイ・ステップ
第3回 標準入出力すりかえのテクニック
シェルスクリプトは、単にプログラムを次々に実行するだけのものではありません。それぞれのプログラムが連係するように、あるプログラムの結果を別のプログラムへと自動的に受け渡す機能があります。それがリダイレクトとパイプです。
さかいひろあき(h.sakai@home.email.ne.jp)
2000/8/30
| echoとはやまびこか? |
今回は、前回作成したコマンドの中身の解説から始めましょう。
echo "Hello World" |
このシェルスクリプトはいったい何をやっているのでしょう? これは誰が何を実行して、どうして画面に文字が表示されるのでしょうか? ふだんなにげなく使っているコマンドでも、少し深く突っ込んでみるとLinux(UNIX)の仕組みや特徴が見えてきます。
実はechoは、「bashの内部コマンド」の1つであり、bash自身によって実行されています。意外に思われた方も多いかもしれません。なぜなら「echo」は外部コマンドとしても存在する(通常は/bin/echo)からです。でも、普通に設定されたLinuxで実行されるechoはbashの内部コマンドのほうです。試しにやってみましょう。
|
|
上は“--version”という文字列をそのまま表示するだけですが、下は“--version”を「バージョンを表示しろ」というオプションと理解して、/bin/echoのバージョンを表示してます。
このように内部コマンドのechoと外部コマンドのechoにはわずかな違いがあります。なぜ2つあるのかは私もわかりません。伝統的にUNIXでそのようになっているようです。
いずれにせよ、echoは指定された「引数」を「標準出力」に出力するようプログラムされています。echoの基本仕様はたったこれだけです。ではこの「引数」と「標準出力」について少し詳しくお話してみましょう。
| 引数とは? |
「引数」とは、コマンドを実行する時にコマンドの後ろに(スペースを空けて)書かれるもののことです。引数を指定することにより、コマンドに違った働きを与えることができます。
引数の中でも通常マイナス(-)で始まり、コマンドに特定の役割を与えるものを「オプション」と呼びます。上記の例で説明すると、内部コマンドのechoは引数“--version”をオプションとは理解せずにそのまま表示しているだけですが、外部コマンドのほうのechoは“--version”をオプションとして理解し、プログラムのバージョンを表示しています。
このように、Linuxのほとんどすべてのコマンドは何らかのオプション(--helpや--versionなど)を指定することができるようになっています。また引数には「ワイルドカード」も使用できます。ワイルドカードは任意の複数文字にマッチする“*”と、任意の一文字にマッチする“?”、および指定された任意の文字のうち1文字にマッチする“[ ]”が使用でき、ファイル名とマッチされます。例えば“abc”“a3b”“a45b”“.abc”の4つのファイルが存在したとすると、
$ echo * |
とやればカレントディレクトリのファイルがピリオド(.)で始まるものを除いてすべて表示されます。ビリオドではじまるファイルはLinuxでは伝統的に隠しファイル、設定ファイルとして使われいるので間違って消したり(rm *などして)しないようになっています。かといってまったく見ることができないわけではなく、以下のようにすればピリオドで始まるファイルにもマッチします。
$ echo .* |
ではいろいろと例を挙げてみます。下記では、1文字に合致する“?”と、囲まれた任意の文字の中の1文字に合致する[ ]を紹介します。
|
|
[ ]はまた、[a-z]や[5-9]などの指定もできます。[a-z]はaからzのアルファベット小文字全て、[5-9]は5から9までの数字にマッチします。
このワイルドカードはMS-DOSやWindowsのcommand.comにも同じような機能があるように見えますが、MS-DOSなどでは、実はそれぞれのアプリケーションがワイルドカードを展開しています。一方、Linux(UNIX)では、シェルがワイルドカードを展開したうえでアプリケーションに渡しています。これは使う人にとってはどうということのない違いですが、アプリケーションを作る側としては、「MS-DOSのプログラム=ワイルドカードの展開を自前でやる」「Linuxのプログラム=ワイルドカードは一切気にしないでよい」という違いがあります(注:MS-DOSのCコンパイラなどにはワイルドカード展開ルーチンが標準で付属していて、プログラマーが意識する必要はないようになっています)。
| 標準出力と、そのすり替え |
こんどは標準出力について説明しましょう。「標準出力」とは、プログラムとOSのあいだでデータをやり取りをする「橋」の役割をします。プログラムが何かを標準出力に出力すると、それはOS(この場合はLinux)に渡されて解釈され、結果として画面に文字が表示される仕組みになっています。このような仕組みになっているおかげで、出力先を「コマンドを実行する段階で」変更することができます。
例えば、echoコマンドが引数の内容を画面に出力する例を紹介しました。
echo "Hello World" |
一方、シェルスクリプトファイルの作成の方法として次のような例も紹介しました。
| $ echo 'echo "Hello World"' > helloworld |
echoが出力した結果を「helloworld」というファイルに出力する方法でした。
では、echoは、画面に出力するときと、ファイルに出力する時でプログラム上の処理を分けているのでしょうか? いいえ、そうではありません。echoあくまでも渡された引数を標準出力に出力する仕事以外はしないのです。2つ目の例にある不等号(>)は「リダイレクト」と呼ばれ、「橋の架け替えをするもの」つまり「標準出力の行き先を変更するもの」です。
OSは図1のようにさまざまなデバイスやファイルへの入出力をサポートします。デバイスとは周辺装置一般のことを指し、画面、キーボード゙、モデム、CD-ROM、メモリカード、テープ装置……とコンピュータで使えるありとあらゆる装置はデバイスとしてOSでサポートされています。
![]() |
| 図1 OSは画面やキーボードなどの入出力をサポート |
通常、実行されたコマンドは図2のように標準出力と画面、標準入力とキーボードが結びつけられています。
![]() |
| 図2 プロセスが実行されると、標準入力と標準出力が結びつけられる |
このリダイレクト処理は、echoコマンドをbashが起動する直前に行っています。上記のシェルスクリプトの処理は次のように行われています。
- 入力されたコマンドechoをbashが認識する。
- 同時にbashは標準出力がhelloworldというファイルにリダイレクトされたことを認識する
- bashがechoコマンドを起動する直前にechoの標準出力をファイルへ変更する(すりかえる)
- echoコマンドは標準出力へ文字を出力する。echoはファイルへ変更されていることは全く意識しない。
- echoにより標準出力(bashによりファイルへすりかえられている)へ出力された情報をOSが受け取り、ファイルへ書き込む。
![]() |
| 図3 標準出力をファイルにすり替えることができる |
この「すりかえ」は、細かい内部処理で言うと「fork」というプロセスを作る処理と「exec」というプログラムを行うことで実現されています。しかしこれについては、また別の機会に書きたいと思います。
| “cat=ねこ” のこと? |
標準出力に対応するものとして、「標準入力」というものが存在します。以下の内容のファイルを作成し、実行してみましょう。ファイル名を「helloworld2」とします。
Helloworld2cat <<EOF |
さっそく実行してみましょう。
$ helloworld2 |
Helloworld2では、「<<EOF」と最後の「EOF」にはさまれた部分を「標準入力」として取り込み、catというプログラムへ渡して実行させています。実はここにある最初の“EOF”は、ほかの文字列であってもなんでもかまいません。ただし、最後の「EOF」(3行目のEOF)は、必ず行頭から始まっている必要があります(スクリプト内でタブなどを使って整形している場合は注意する必要があります)。
標準入力は標準出力と同じように、デフォルトでは画面から(つまりプロンプトから)の入力に割り当てられています。しかしこのように、その標準入力も、リダイレクトを使って「すりかえ」ができます。
catというコマンドは詳しく言うと、「与えられた引数をファイルとして認識し、それらをつなげて標準出力へ出力する。引数が存在しない場合は、標準入力から読み込んで標準出力へ出力する」というコマンドです。今回の例題では、「引数が存在しない場合」の使い方に相当します。もともとはこのcatという名前は「ファイルをつなげる」という意味の英語のconcatenateから来ています。残念ながら「ねこ」ではありません。
ではこのcatを使って、いろいろやってみましょう。
$ echo "Hello World" >
testfile |
すでに解説したとおり、リダイレクトによりファイルへ文字を出力しています。これをcatで出力してみます。
$ cat < testfile |
この例はどうでしょうか? さきほどとは逆向きのリダイレクト(<)ですね。これは「標準入力」を「ファイル」に「すりかえ」することを表します。catにしてみれば、標準入力がすりかえられたことなどおかまいなしですから、最初の例と全く同じように標準入力から読み込んで標準出力へ出力しているだけです。
| 標準出力と標準入力をつなげる |
次にこれはどうでしょうか?
| $ echo "Hello World" | cat |
縦棒(|)は「パイプ」と呼ばれ、1つめのコマンド(パイプの左側)の「標準出力」を2つ目のコマンドの「標準入力」に渡す働きをします。1つめのプログラム(またはコマンド)の標準出力をOS内部の「パイプ」というファイルに保存し、2つめのプログラムにそのファイルを渡している、という理解をするとわかりやすいかもしれません。ここでも2つのプログラムとも、パイプを意識することは決してありません。単に標準出力、標準入力に対して読み書きしているだけです。
![]() |
| 図4 複数のプロセスでも標準入力と標準出力をつないでいくことで連係させることができる。それがパイプの役割だ |
この「すりかえ」ができることはシェルスクリプトの基本となります。ほかのプログラム言語やスクリプトと違い、シェルスクリプトとは元々存在するプログラムを組み合わせて、リダイレクトなどを駆使し、ある機能を組みあげていくものなのです。
では、それはperlなどのスクリプト言語とどう違うのでしょうか?。Perlはすばらしいスクリプト言語で、世界でいちばん使われているといっても過言ではありません。これまでの例でやったようなことは当然すべてPerlでも実現できます。ただ、Perlでなにかをやりたいときは、ほとんどすべてを「Perlの言葉」で表現しなくてはなりません(もちろんPerlでも外部コマンドの起動はできます)。
一方シェルスクリプトでは、それぞれ独立したプログラムを組み合わせていきます。標準入出力型のプログラムであれば、ここで紹介したリダイレクトとパイプを使って自由に組み合わせることができますし、そうでなくても、そのコマンドを実行するだけのことも当然できます。
もしあなたが新しい標準入出力型のプログラムを作ったとしましょう。そのコマンドにはまだ並び替え機能がなかったとします。その場合であっても、シェルスクリプトであれば、以下のように簡単に、結果を並び替えて表示する機能を実現できます。
| $ my_program | sort |
今後シェルスクリプトを勉強していく中では、つねにこの「すりかえ」機能を頭にいれながらすすめていくことにしましょう。
| 連載 ステップ・バイ・ステップ・シェルスクリプト |
| Linux Squareフォーラム プログラミング関連記事 |
| 特集:オブジェクト指向に生まれ変わるPHP5[前編] 現在開発中のPHP5は、オブジェクト指向機能が大幅に強化される。次世代PHPはどのような言語になるのか? |
|
| 特集:Windows開発者に贈る
Kylixの全貌 注目の開発環境「Borland Kylix」がいよいよ見えてきた。ここに、英語版の発売を目前に控えたKylixの機能やアーキテクチャを紹介しよう |
|
| 特集:Kylixプログラミング作法 GUIの構築やコンポーネントとコードの関係、 Object Pascalの仕様など。 これらの点を、実際に日本語ベータ版でプログラミングしながら分かりやすく解説 |
|
| 連載:PHP4で作るWeb-DBシステム(全5回) PHPはWebサーバとデータベースを結びつけるものだ。そのためPHPでの開発を開始するには、OS、データベース、Webサーバ、そしてPHPと、多くのソフトウェアのインストールを行う必要がある |
|
| 連載:ステップ・バイ・ステップ・シェルスクリプト(全7回) Linuxの中でシェルスクリプトはネットワークの設定、デーモンの起動など重要な役割を果たしている。この連載では、シェルスクリプトで実用的なプログラムを組むことを目標にして、シェルの基本的な知識を説明する |
|
| 連載:Kylix
3とDB2で作るWebサービス・アプリ(全5回) Kylix 3とDB2 V8.1を使って、Webサービス・アプリを作ってみよう。トライアル版も用意されているので、実際に試しながら読んでほしい |
|
|
TechTargetジャパン
- OSSライセンスの採用傾向に「変化」あり (2012/5/21)
OSS普及の一翼を担ってきたライセンス、GPLファミリー採用の割合が減少傾向にあるそうです。いったいどうして? - ここからFirefoxの反撃が始まる (2012/3/12)
2月のLinux SquareのランキングではFirefoxの記事がダントツのページビューを集め、トップに立ちました - CMakeでMySQLをビルドしてみる (2012/3/8)
ここまでの作業でCMakeを使う準備が整いました。今回はひとまずMySQLをビルドしてみます - MySQLのビルドに欠かせないCMakeを準備する (2012/3/2)
今回は、MySQLをビルドするために欠かせないツール「CMake」をインストールし、使う準備をします
|
|
キャリアアップ
スポンサーからのお知らせ
- - PR -
イベントカレンダー
- - PR -




