今回はUNIX系の得意分野であるデータを整形して表にするというネタです。大量のデータならSQLが使えるデータベースの方がよいのでしょうけど、今時のパソコンは相当のパワーがあります。1970〜1980年代のUNIXマシンと比較すべくもなく桁違いのパワーがあります。ですので、結構なデータ量であってもSQLなどを使わなくても十分実用的な処理ができます。
ということで今回は本格的なデータベースがない時代(1977年)に作られたAWK(オーク)を使ってみます。
・AWK
https://ja.wikipedia.org/wiki/AWK
今回もこれまで同様にサンプルで利用するファイル・ディレクトリはデスクトップのsampleディレクトリとしています。デスクトップにsampleディレクトリがない場合は作成しておいてください。(コマンド入力ならmkdir ~/Desktop/sampleとして作成することができます)
また、カレントディレクトリも上記の場所になります。cd ~/Desktop/sampleのようにコマンドを入力してカレントディレクトリを変更しておけばよいでしょう。
単純なデータを処理
それではAWKを使って簡単なデータを処理してみます。AWKは結構いろいろできますが、複雑になりそうだなと思ったらSQLでもプログラムでも他の手段を使うことを推奨します。もちろんアプリケーションでも構いません。目的のためなら手段を選ばず、という感じで良いのではないかと思います。大昔と違って選択肢はたくさんあります。ただ、古くからあるものは技術的に枯れているのと最初から入っているので、多くの環境で使えるというメリットがあります。メリットとデメリットを比べてメリットのある方を使えば良いでしょう。
最初に処理するデータを用意します。ここでは適当に入力した10個の整数値を利用します(一応冷蔵庫内の温度データだと考えてください)。名目としてはラズベリーパイなどIoT機器で計測した温度データを行単位で保存したものになります。
・pi1.txt
6
8
10
9
6
5
3
0
-3
-8
まず、これらのデータを単純に表示(出力)してみましょう。AWKは最初にパターン、次にアクションを指定します。その後に処理するファイル名(ファイルパス)を指定します(標準入力からも受け付けます)。パターンは省略できます。省略するとすべてのデータが対象になります。アクションは省略するとエラーになるのでawk '' pi1.txtのように何か指定しておく必要があります。
AWKでデータをすべて表示するには以下のようにします。pi1.txtが内容を表示するファイル名になります。
awk '{print}' pi1.txt
なお、以下のように指定しても問題なく処理されますが、'(シングルクオート)で囲まないと使用する記号によってはシェルが処理してしまいエラーや予期せぬ結果になることがあります。ですので ' で囲んでおくようにしましょう。
awk {print} pi1.txt
AWKでは行単位でなく列単位でも処理ができるようになっています。1列目だけを表示するにはprintの後に$1を指定します。ちなみに2列目なら$2、3列目なら$3というようになります。
また、$0は行全体になります。pi1.txtファイルは列が1つしかありませんので$0を指定しても$1を指定しても同じ結果になります。
awk '{print $1}' pi1.txt
awk '{print $0}' pi1.txt
データではなくて単純に文字列を表示したい場合はprintの後に"〜"で囲みます。以下のコマンドを実行すると同じ文字列が10個表示されます。これはpi1.txtにあるデータの数が10個あるためです。
awk '{print "何となくコマンド"}' pi1.txt
1回だけ表示すれば十分という場合はパターンを終了させます。ENDをアクションの前に指定します。これで1回だけ指定した文字列が表示されます。
awk 'END{print "何となくコマンド"}' pi1.txt
条件をつけてデータを取り出す
次に条件をつけてデータを取り出してみましょう。pi1.txtのデータ内にある負数(マイナスの数値)だけピックアップしてみます。この場合、値は$1に入っていますので、この値が0より小さいかどうかを判定します。これは以下のように不等号記号を使って条件のみを指定します。
awk '$1<0 {print $1}' pi1.txt
負数のみが表示されました。0を含みたい場合は<=のように指定します。
awk '$1<=0 {print $1}' pi1.txt
0よりも大きい値だけを表示する場合は以下のようになります。
awk '$1>0 {print $1}' pi1.txt
0以外を表示する場合は!=を使って以下のように指定します。
awk '$1!=0 {print $1}' pi1.txt
行番号をつけて表示
データを手軽にピックアップすることができましたが、先ほどの例ではピックアップされたデータが、何行目なのかがわかりません。そこで今度はピックアップしたデータとともに行の位置を示す行番号も一緒に表示するようにしてみます。
AWKではあらかじめ用意された変数があります。行番号はNRという名前の変数が保持しています。最初の行を処理する場合はNRには1が入ります。以下のようにするとpi1.txtのデータの数と同じ1から10までの数値が表示されます。
awk '{print NR}' pi1.txt
この行番号とデータを:(コロン)で区切って表示してみます。この場合は以下のように指定します。
awk '{print NR":"$1}' pi1.txt
行番号を2桁にしたい場合はprintでなくprintfを使います。printfについては以前説明したものとだいたい同じですので、指定できる書式については、そちらを参照してください(第79回)。
2桁にするには%02dを、4桁にするには%04dを指定します。なお、\nを指定しないと改行されませんので注意してください。
awk '{printf "%02d\n",NR}' pi1.txt
awk '{printf "%04d\n",NR}' pi1.txt
それではピックアップしたデータに行番号をつけて表示してみましょう。以下のようにするとピックアップしたデータに行番号が付きます。これなら該当データが何行目にあるか、すぐにわかります。
awk '$1<0 {print NR":"$1}' pi1.txt
最後に条件をつけてピックアップしたデータの個数を表示してみましょう。この場合はパイプ(|)とwcコマンドを組み合わせます。
awk '$1<0 {print}' pi1.txt | wc -l
次回は複数の列を持つデータを処理してみます。
著者 仲村次郎
いろいろな事に手を出してみたものの結局身につかず、とりあえず目的の事ができればいいんじゃないかみたいな感じで生きております。


































