これまで、sortで整列したり、grepで探索したりと、色々なコマンドを利用してきました。 しかし、どれもこれも、ちょっとしたことしかできません。 こんなもので、本当に役に立つのでしょうか。
UNIXでは、小さな道具を組み合わせて本格的な道具にする、という考え方をします。 つまり、多機能のコマンドを大量に用意するのではなく、単機能のコマンドをある程度用意し、必要に応じてそれらを組み合わせるのです。 利用者の工夫次第で、いくらでも便利な道具が作り出せるわけです。
例えば、テキスト・ファイルの5行目を表示したいとします。 このとき、5行目を表示するようなコマンドを用意する必要はありません。 最初の5行を取り出してから、最後の1行を表示すれば、5行目は表示されます。 したがって、最初の数行を表示するheadコマンドと、最後の数行を表示するtailコマンドを組み合わせればよいのです。
パイプ とは、順番にデータを入れると、そのままの順番でデータが出てくる仕組みです。 管の中をデータが流れている様子を想像してください。 パイプを使えば、コマンドを組み合わせることができます。
UNIXシェルでは、記号"|"がパイプを表します。 パイプの形式は
command1|command2
です。 このコマンドを入力しますと、まず、コマンド command1 が実行されます。 その結果は画面には表示されず、パイプに入ります。 そして、そのままパイプから出てきて、それに対して 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コマンドは、引数のファイルからデータを読み込み、その最後の数行を表示するものです。 ここでは、引数ではなく、パイプからデータを読み込みます。 したがって、引数を書かないのです。
パイプを利用する場合、多くのコマンドでは、引数を書けばそのファイルからデータを読み込み、引数を書かなければパイプからデータを読み込みます。
次の例は、探索件数を数えるものです。 これは、文字列を探索するgrepコマンドと、行数を数えるwcコマンドを組み合わせればできます。 以下では、晴れ(Fine)の日が何日あるかを求めています。
b04a001@AsiaA1:~/comp2d% cat weather01.txt October 1 Sunday Cloudy October 2 Monday Fine October 3 Tuesday Cloudy October 4 Wednesday Cloudy October 5 Thursday Rainy October 6 Friday Rainy October 7 Saturday Fine b04a001@AsiaA1:~/comp2d% grep Fine weather01.txt October 2 Monday Fine October 7 Saturday Fine b04a001@AsiaA1:~/comp2d% grep Fine weather01.txt | wc 2 8 46
ここで、以下の内容をファイル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 weather01.txt October 1 Sunday Cloudy October 2 Monday Fine October 3 Tuesday Cloudy October 4 Wednesday Cloudy October 5 Thursday Rainy October 6 Friday Rainy October 7 Saturday Fine b04a001@AsiaA1:~/comp2d% awk '{print $4}' weather01.txt Cloudy Fine Cloudy Cloudy Rainy Rainy Fine b04a001@AsiaA1:~/comp2d% awk '{print $4}' weather01.txt | sort Cloudy Cloudy Cloudy Fine Fine Rainy Rainy b04a001@AsiaA1:~/comp2d% awk '{print $4}' weather01.txt | sort | uniq Cloudy Fine Rainy b04a001@AsiaA1:~/comp2d%
uniqコマンドでは、何行連続しているかも求められます。 形式は
uniq -c file
です。
以下では、天気の種類ごとの日数を求めています。
b04a001@AsiaA1:~/comp2d% awk '{print $4}' weather01.txt | sort Cloudy Cloudy Cloudy Fine Fine Rainy Rainy b04a001@AsiaA1:~/comp2d% awk '{print $4}' weather01.txt | sort | uniq -c 3 Cloudy 2 Fine 2 Rainy b04a001@AsiaA1:~/comp2d%
ここでは、例題として、英文テキストに単語が何種類使われているかを調べます。 注意点は、"This"と"this"は同じ単語であることです。 ただし、話を簡単にするために、"pen"と"pens"は違う単語とします。 以下のような手順でテキスト処理を行えば、答えが出てきます。
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種類の単語が使われたことが分かります。
コマンドを使って、ファイルenglish01.txtの中では、どの単語が何回使われいるかを求めてください。
b04a001@AsiaA1:~/comp2d% ??? 2 a 3 is 1 it 2 pen 2 this 1 yes
余力のある人は、オリジナルの英文テキスト(数行でよい)をファイル(例えばenglish02.txt)に保存し、コマンドを使って、どの単語が何回使われいるかを求めてください。
今日の演習4の答案(「ターミナル」画面のコピー)をメールでkonishi@twcu.ac.jp宛に提出してください。 メールを送るときは、大学のパソコンを使うか、大学のメール・サーバに接続するかして、差出人が大学のメール・アドレスになるようにしてください。 メールの本文には、学生番号、氏名、科目名、授業日(10月18日)を明記してください。