ラベル awk の投稿を表示しています。 すべての投稿を表示
ラベル awk の投稿を表示しています。 すべての投稿を表示

2014年11月17日月曜日

Unixテキスト処理コマンド集【cat, head, tail, grep, sort, join, awk】

テキスト形式のデータ処理に便利なUnixコマンドを紹介します。
Unixコマンドは無数にあるのですべてをカバーすることは出来ません。

ここではお手軽に一行で書けるコマンドを中心に扱います。多くの「ちょっとした処理」はこれらの組み合わせで行うことが出来ます。


cat

cat <オプション> <ファイル>

全文を出力する。いわずもがななコマンド。
元々ファイルをつなげる(concatenate)為に実装されたコマンドですが、主に小さいファイルのダンプの為に使われています。
有用なオプションとしては-n: 行番号を出力するというものがあります。これを使うとコンパイルエラーの出た箇所の確認などに便利です。

cat run.sh -n
     1    #!/bin/sh
     2   
     3   
     4    # arg1 = time
     5    #
     6    #
     7   
     8    cd $PBS_O_WORKDIR
     9    ./tiles$time $algname $PBS_ARRAYID $thread_number $param1 $param2 $param3 < $problem_type
    10   
ちなみにcatの語源はconcatenate(つなげる)の略形です。


head

head <オプション> <ファイル>

ファイルの先頭の10行を出力する。大きなデータファイルを確認する場合や、ファイルヘッダーのみ確認する場合に便利です。

オプション-nで任意の行数を出力することが出来ます。
例えば
head  -n 20 astar.dat
ならば先頭20行が出力されます。
head -n -20 astar.dat
とすると最後の20行以外のすべての行を出力します。
ただしheadと続くtailはUnixのディストリビューションによって若干異なるインターフェイスを持っています。中身は同じなので大きな違いはありませんが、manページを見ておく必要はあると思います。

ちなみにheadとtailで行番号を出力したい場合は
cat astar.dat -n | head -n -20
のようにすれば出来ます。この場合の行番号は元のファイルにおける行番号になります。


tail

tail <オプション> <ファイル>
ファイルの末尾の10行を出力する。headと相似形であるので説明はheadを見てください。


grep

grep [オプション] パターン [ファイル...]
grep [オプション] [-e パターン | -f ファイル] [ファイル...]
パーサとして優秀なコマンド。特にログから必要なデータをマイニングする場合によく使われます。
例えば、
grep cron /var/log/syslog
とおくとファイル/var/log/syslogの中で文字列"cron"を含む行を出力します。cronジョブのデバッグをする場合はこれを読むと原因がすぐに分かります。
このコマンドを熟知していれば「ログが多すぎて必要なデータが分からなくなってしまった」ということはありません。

オプションやトリックは様々あるのですべてを網羅することは出来ませんがいくつか基本のものを紹介します。


-c, --count
通常出力の代わりにパターンに一致した行が何行あったかを出力する。
-l, --files-with-matches
通常出力の代わりにパターンに一致した行のあるファイルの名前を出力する。

大規模なデータを扱う場合はgrepの通常出力が大きくなりすぎて扱いにくくなってしまうことがありあます。大きな詳細を扱うのではなく、より大きな傾向を見る場合に使いやすいオプションです。木ではなく森を見るためのコマンドといえるでしょう。

語源はテキストエディタedのGlobal Regular Expression Printから。


sort

sort [OPTION]... [FILE]...
ファイルの行をソートする。デフォルトだと先頭のフィールドに基づいてソートされる。
データは順番が重要になることがあります。例えばgnupotは一行ずつ読み込んで処理するシステムの一つです。plot with linesとするとデータ入力順に線を引いていきます。

デフォルトだと入力文字列を文字列としてみなしてソートする。どういうことかというと、以下のtest.txtをソートすると10が2よりも前にくるということです。
$ cat test.txt
0 zero
1 one
2 two
10 ten
 これをsortすると、
$ sort test.txt
0 zero
10 ten
1 one
2 two
2どころか1よりも手前にきてしまいます。フィールドを数字としてみなしてソートする為には-nオプションをつける必要があります。
$ sort sort.txt -n
0 zero
1 one
2 two
10 ten

join

join [OPTION]... FILE1 FILE2
二つのファイルの内部結合(inner join)を出力する。
比較データなどを1ファイルにまとめる場合などに便利です。
-aコマンドでouter joinにすることが出来る。

結合フィールドはソートされている必要があるので、前述のsortを使うことになります。sortされていない形を保つ必要がある場合はcat -nで行番号を加えることで便宜的なイテレーション番号をつけ、それに基づいてソートをするということが出来ます。


awk

awkは一行でテキスト処理を行う軽快なコマンドであると同時に表現力豊かなプログラミング言語でもあります。awkのスクリプトを書けばこれまで述べてきたコマンドをawkで実装することも出来ます。しかしながらここでは一行でかける簡単な処理に絞って説明をします。詳しい言語実装を知りたい方は下記リンクをご参照下さい。

awkの基本骨子は

1. データファイルを一行読み込む
2. パターンマッチングを行う
3. パターンにマッチした場合に処理を行う

です。例えば
awk '/error/{print $1, $2}'
とすれば"error"の文字列を含む行の1番目、2番目の語を出力するという処理になります。

パターンマッチングの部分はgrepに似ていますが、awkの方がより深入りをして細かい場合分けや出力の指定をすることが出来ます。

データのフォーマットを変えたり、複数データから平均を計算したり、gnuplotに渡すデータを作成したり、shell scriptの中で活躍できるコマンドです。 結構しっかりとした言語なので詳解な説明は下記リンクに譲ります。

*awk参考リンク

The GNU Awk User's Guide
フルドキュメント。非常に詳解なので困ったらこれを見ればいいでしょう。

AWK入門(ドットインストール)
awkの入門の為ならこちらをお勧めします。awkのしっかりとした言語であるという側面と、簡単に記述できるという側面の両方を見ることが出来ます。


2014年9月21日日曜日

テキスト処理の為に学ぶべき4つの技術

テキスト処理を学ぶべき理由 

コードに限らず、テキストは常に扱う対象になります。
コードを書くことには熱心でもテキスト処理を学ぶことに熱心ではない方は結構います。
しかし、テキストはコードと同様に学ぶべき対象なのです。その理由を2点説明します。

 1. ルーチンワークからプログラミングへ

ログやデータの解析はルーチンワークではありません。

テキストとしてのデータは人間が読める対象である場合が殆どでしょう。
人間が読めるデータですから、一行ずつ直接データを読み、必要な作業を手で行うことはできます。
しかしこれはひどく退屈なルーチンワークにしかなりません。
テキストをプログラミングの対象として扱う方法や技術を学ぶことでルーチンワークを排して楽しいプログラミングをすることが出来ます。

2. プログラマの生産性を向上させる

テキスト処理は手作業でやろうとすると思う以上に時間がかかるものです。
プロジェクト全体のコメントのフォーマットを変更する、などは手作業でやることも出来ますが、手作業だと変更し忘れるファイルがあったりすることは良くあります。
チェックの時間も含めると手作業による効率はあまりよくないことが分かると思います。




以下で紹介する技術は全て一朝一夕で出来るものではありません。むしろ一生かけて学ぶものの一つを紹介することを目的に記事を書きました。
しかし前述のようにこれらの技術は一生使うに能う理由があります。
是非触って見てください。



1. テキストエディタ



当然ですがテキストエディタを扱うということは最も重要なことになるでしょう。

しかし、テキストエディタは熟練度による生産性の差が明瞭に表れるものの一つでしょう。
ViやEmacsなどのエディタは単純に文字を一つずつ打つという機能だけではありません。
文字列置換や様々なユーティリティがあり、また様々なショートカットキーがあります。
これらの機能は直感的ではない所が結構あったりします。それはこれらのキーが熟練者に最適であるようにデザインされているからであり、入門しやすいようになっている訳ではないからです。
この点が多くのIDEや商業ソフトウェアのUIとの違いでしょう。

入門が簡単なエディタと、熟練者にとって最適なエディタ。
一生プログラミングを続けるなら、どちらを選ぶべきかは自明でしょう。


2. awk

テキスト処理と言えばawkです。
awkはテキスト処理だけの為に開発されたという男らしいプログラミング言語です。manページも3ページしかありません。しかしテキスト処理という点に関しては不足のない言語です。

awkの基本的なアルゴリズムはパターンマッチングです。
入力テキストを行毎に読み込み、その行がパターンに合致していたら処理を行う。
これを最終行に行くまで繰り返す。

非常に簡潔で明解な言語です。文法も簡潔なので殆どの処理は一行(one liner)で済ませることが出来ます。

awk '/error/{print $1, $2}'

とすればerrorの文字列を含む行の1番目、2番目の語を出力するという処理になります。

awkは特にデータの解析に有用です。
gnuplotなどにデータを流し込む前の前処理を行ったり、統計値を取ったり、 データからデータを取り出すような処理に対して威力を発揮します。


参照リンク

The GNU Awk User's Guide
フルドキュメント。非常に詳解なので困ったらこれを見ればいいでしょう。

AWK入門(ドットインストール)
awkの入門の為ならこちらをお勧めします。awkのしっかりとした言語であるという側面と、簡単に記述できるという側面の両方を見ることが出来ます。



3. grep

grepは文字列検索の為のコマンドです。
作業のチェックやログの解析などに用いられます。

例えばプログラム中に埋め込んだTODO:をすべて読み込むには

grep -n TODO: main.cpp

とすれば

118:        // TODO: Array of dynamic sized objects.
124:        // TODO: temporal buffer to store nodes from income buffer.
147:            // TODO: Get nodes from income buffer and put it into open list.
170:            // TODO: minf(int f):
221:            // TODO: incumbent solution.
223:                // TODO: For some reason, sometimes pops broken node.
245:                //                TODO: need it to be atomic.
277:                // TODO: Push items to thread safe income buffer.
289:                // TODO: trylock
372:        // TODO: Time to printing these texts are included in the walltime.
377:        // TODO: pack to a method

のように出力され、進捗状況が概観するのに使えます。
awkと比較すると、grepは出力を編集するためのものではなく、インタラクティブに、テキストがどうなっているのかを把握するために使いやすいように思います。

grepによるパターンの検索(Oracle)


4. Ruby or Python

やや大規模なテキスト処理を行う場合、シェルスクリプトやawkでは表現力が足りなかったり、あるいは読みやすいコードにならない場合があります。しかしテキストデータに対してC++やJavaで書くのはオーバーキルな場合が多いです。

RubyやPythonのような言語を理解しているとこういうちょっとしたプログラムを実装するのにも役に立ちます。





先に述べましたように、これらの技術は小手先技ではなく、一朝一夕に得られるものではありません。しかしスケールアップしていくものです。
一生使える技術を学びましょう。