[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

コンピュータIID(UNIXとHTML)第4回

目次
4.1 パイプ
4.1.1 道具の組み合わせ
4.1.2 パイプとは
4.1.3 フィルタ
4.1.4 パイプの使用例
4.2 リダイレクト
4.3 演習4
4.4 レポート課題
4.5 参考文献
索引

4.1 パイプ

4.1.1 道具の組み合わせ

これまで、sortで整列したり、grepで探索したりと、色々なコマンドを利用してきました。 しかし、どれもこれも、ちょっとしたことしかできません。 こんなもので、本当に役に立つのでしょうか。

UNIXでは、小さな道具を組み合わせて本格的な道具にする、という考え方をします。 つまり、多機能のコマンドを大量に用意するのではなく、単機能のコマンドをある程度用意し、必要に応じてそれらを組み合わせるのです。 利用者の工夫次第で、いくらでも便利な道具が作り出せるわけです。

例えば、テキスト・ファイルの5行目を表示したいとします。 このとき、5行目を表示するようなコマンドを用意する必要はありません。 最初の5行を取り出してから、最後の1行を表示すれば、5行目は表示されます。 したがって、最初の数行を表示するheadコマンドと、最後の数行を表示するtailコマンドを組み合わせればよいのです。

4.1.2 パイプとは

パイプ とは、コマンドにおいて、データを左から右へ伝える仕組みです。 管の中で、左から右へデータが流れる様子を想像してください。 パイプを使えば、コマンドを組み合わせることができます。

UNIXシェルでは、記号"|"がパイプを表します。 パイプの形式は

command1|command2

です。 このコマンドを入力しますと、まず、コマンド command1 が実行されます。 その結果は画面には表示されず、パイプによって command2 に伝えられます。 そして、 command2 が実行されます。 最終結果は画面に表示されます。

パイプは何段階も使えます。 2段階ですと、

command1|command2|command3

となります。 コマンド command1 が実行され、その結果がパイプによって伝えられ、 command2 が実行され、その結果がパイプによって伝えられ、 command3 が実行されます。 まるで、コマンドとコマンドを結ぶ管の中を、データが流れるようなものです。

最初の例の、5行目を表示するコマンドは、次のようになります。

b04a001@AsiaA1:~% cd comp2d
b04a001@AsiaA1:~/comp2d% cat month01.txt
January
February
March
April
May
June
July
August
September
October
November
December
b04a001@AsiaA1:~/comp2d% head -5 month01.txt
January
February
March
April
May
b04a001@AsiaA1:~/comp2d% head -5 month01.txt | tail -1
May
b04a001@AsiaA1:~/comp2d%

ここで、tailコマンドに引数がないことに注意してください。 もともと、tailコマンドは、引数のファイルからデータを読み込み、その最後の数行を表示するものです。 ここでは、引数ではなく、パイプからデータを読み込みます。 したがって、引数を書かないのです。

パイプを利用する場合、多くのコマンドでは、引数を書けばそのファイルからデータを読み込み、引数を書かなければパイプからデータを読み込みます。

ここで、以下の内容のテキスト・ファイルcafe01.txtを作成します。

Jack tea
Ben juice
Mike coffee
Ted tea
Bill coffee

次の例は、探索件数を数えるものです。 これは、文字列を探索するgrepコマンドと、行数を数えるwcコマンドを組み合わせればできます。 以下では、コーヒー(coffee)を注文した人の数を求めています。

b04a001@AsiaA1:~/comp2d% cat cafe01.txt
Jack tea
Ben juice
Mike coffee
Ted tea
Bill coffee
b04a001@AsiaA1:~/comp2d% grep coffee cafe01.txt
Mike coffee
Bill coffee
b04a001@AsiaA1:~/comp2d% grep coffee cafe01.txt | wc
       2       4      24
b04a001@AsiaA1:~/comp2d%

4.1.3 フィルタ

ここで、以下の内容をファイルenglish01.txtに保存します。

This is a pen.
Is this a pen?
Yes, it is.

コマンドの中には、引数でファイルが指定できず、専らパイプからデータを読み込むものがあります。 そのようなコマンドを フィルタ と呼びます。 引数でファイルが指定できても、普通はパイプからデータを読み込むなら、フィルタと呼ぶことが多いです。

trコマンド (TRanslate)は、文字を置き換えたり削除したりするフィルタ・コマンドです。 置き換える場合の形式は

tr string1 string2

です。 これで、 string1 の1文字目が string2 の1文字目に置き換えられ、 string1 の2文字目が string2 の2文字目に置き換えられ、…となります。

例えば、アルファベットをすべて大文字にするには、

tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ

とします。 もちろん、これでは大変なので

tr a-z A-Z

と省略できます。

b04a001@AsiaA1:~/comp2d% cat english01.txt
This is a pen.
Is this a pen?
Yes, it is.
b04a001@AsiaA1:~/comp2d% cat english01.txt | tr a-z A-Z
THIS IS A PEN.
IS THIS A PEN?
YES, IT IS.
b04a001@AsiaA1:~/comp2d%

テキスト・ファイルのスペースを改行に置き換えれば、一行に一単語という、バラバラの状態になります。 このような目的にも、trコマンドが使えます。 改行を直接書くことはできませんが、"\n"と書きますと、改行を意味します。 スペースも"\n"も、シングルクオートで囲みます。

b04a001@AsiaA1:~/comp2d% cat english01.txt | tr ' ' '\n'
This
is
a
pen.
Is
this
a
pen?
Yes,
it
is.
b04a001@AsiaA1:~/comp2d%

trコマンドの、削除する場合の形式は

tr -d string

です。 これで、 string の中の文字が削除されます。

以下では、句読点を取り除いています。

b04a001@AsiaA1:~/comp2d% cat english01.txt | tr -d '.,?'
This is a pen
Is this a pen
Yes it is
b04a001@AsiaA1:~/comp2d%

uniqコマンド (UNIQue)は、同じ行が連続しているとき、それらを一つにまとめます。 形式は

uniq file

です。

uniqコマンドは、普通はsortコマンドと一緒に使います。 同じ行があちこちにあるファイルは、sortで整列しますと、同じ行は一か所に固まります。 そして、uniqでフィルタをかけますと、一つになります。

以下では、注文の種類を求めています。

b04a001@AsiaA1:~/comp2d% cat cafe01.txt
Jack tea
Ben juice
Mike coffee
Ted tea
Bill coffee
b04a001@AsiaA1:~/comp2d% awk '{print $2}' cafe01.txt
tea
juice
coffee
tea
coffee
b04a001@AsiaA1:~/comp2d% awk '{print $2}' cafe01.txt | sort
coffee
coffee
juice
tea
tea
b04a001@AsiaA1:~/comp2d% awk '{print $2}' cafe01.txt | sort | uniq
coffee
juice
tea
b04a001@AsiaA1:~/comp2d%

uniqコマンドでは、何行連続しているかも求められます。 形式は

uniq -c file

です。

以下では、注文の種類ごとの数を求めています。

b04a001@AsiaA1:~/comp2d% awk '{print $2}' cafe01.txt | sort
coffee
coffee
juice
tea
tea
b04a001@AsiaA1:~/comp2d% awk '{print $2}' cafe01.txt | sort | uniq -c
   2 coffee
   1 juice
   2 tea
b04a001@AsiaA1:~/comp2d%

4.1.4 パイプの使用例

ここでは、例題として、英文テキストに単語が何種類使われているかを調べます。 注意点は、"This"と"this"は同じ単語であることです。 ただし、話を簡単にするために、"pen"と"pens"は違う単語とします。 以下のような手順でテキスト処理を行えば、答えが出てきます。

  1. 句読点を取り除く。
  2. アルファベットを小文字にする。
  3. 一行に一単語となるようにする。
  4. 整列する。
  5. 重複を取り除く。
  6. 行数を数える。
b04a001@AsiaA1:~/comp2d% cat english01.txt
This is a pen.
Is this a pen?
Yes, it is.
b04a001@AsiaA1:~/comp2d% cat english01.txt | tr -d '.,?'
This is a pen
Is this a pen
Yes it is
b04a001@AsiaA1:~/comp2d% cat english01.txt | tr -d '.,?' | tr A-Z a-z
this is a pen
is this a pen
yes it is
b04a001@AsiaA1:~/comp2d% cat english01.txt | tr -d '.,?' | tr A-Z a-z | tr ' ' '\n'
this
is
a
pen
is
this
a
pen
yes
it
is
b04a001@AsiaA1:~/comp2d% cat english01.txt | tr -d '.,?' | tr A-Z a-z | tr ' ' '\n' | sort
a
a
is
is
is
it
pen
pen
this
this
yes
b04a001@AsiaA1:~/comp2d% cat english01.txt | tr -d '.,?' | tr A-Z a-z | tr ' ' '\n' | sort | uniq
a
is
it
pen
this
yes
b04a001@AsiaA1:~/comp2d% cat english01.txt | tr -d '.,?' | tr A-Z a-z | tr ' ' '\n' | sort | uniq | wc
       6       6      21
b04a001@AsiaA1:~/comp2d%

結局、6種類の単語が使われたことが分かります。


4.2 リダイレクト

コマンドを実行しますと、その結果は画面に表示されます。 リダイレクト という機能を利用しますと、コマンドの実行結果をファイルに保存することができます。

ファイルに保存する場合、リダイレクトの形式は

command > file

です。 このコマンドを入力しますと、コマンド command の実行結果がファイル file に保存されます。 command の部分では、パイプも使えます。 注意点は、コマンドの実行前にファイル file が存在すれば、その内容が消えてしまい、 command の実行結果に置き換わることです。

以下では、コーヒー(coffee)を注文した人の名前を、ファイル cafe02.txt に保存しています。

b04a001@AsiaA1:~/comp2d% cat cafe01.txt
Jack tea
Ben juice
Mike coffee
Ted tea
Bill coffee
b04a001@AsiaA1:~/comp2d% grep coffee cafe01.txt
Mike coffee
Bill coffee
b04a001@AsiaA1:~/comp2d% grep coffee cafe01.txt | awk '{print $1}'
Mike
Bill
b04a001@AsiaA1:~/comp2d% grep coffee cafe01.txt | awk '{print $1}' > cafe02.txt
b04a001@AsiaA1:~/comp2d% cat cafe02.txt
Mike
Bill
b04a001@AsiaA1:~/comp2d%

4.3 演習4

コマンドを使って、ファイルenglish01.txtの中では、どの単語が何回使われているかを求めてください。

b04a001@AsiaA1:~/comp2d% ???
   2 a
   3 is
   1 it
   2 pen
   2 this
   1 yes
b04a001@AsiaA1:~/comp2d% 

余力のある人は、オリジナルの英文テキスト(数行でよい)をファイル(例えばenglish02.txt)に保存し、コマンドを使って、どの単語が何回使われているかを求めてください。


4.4 レポート課題

今日の演習4の答案(「ターミナル」画面のコピー)をメールで提出してください。 差出人は学内のメール・アドレス(b04a001@cis.twcu.ac.jpなど)とし、宛先はkonishi@cis.twcu.ac.jpとします。 メールの本文には、学生番号、氏名、科目名、授業日(10月17日、10月19日)を明記してください。


4.5 参考文献


[小西ホームページ]   [目次・索引]   [前の授業]   [次の授業]

2007年10月17日更新
小西 善二郎 <konishi@cis.twcu.ac.jp>
Copyright (C) 2007 Zenjiro Konishi. All rights reserved.