LoginSignup
36

More than 5 years have passed since last update.

commander.jsでらくらく集計バッチ作成

Posted at

簡単なログファイルの処理にはshell scriptやperlなどを使っていましたが、大きくなく、かつ、大したことがない処理にnode.jsでちゃちゃっと書くことが増えて来ました。

その理由として、d3.jsがcsvやt svをparseしてくれたり、配列の集計などのメソッドが揃っているがあります。

この投稿では、下記2つのモジュールの使い方をご説明します。

  1. commander.js
  2. d3.js

d3.js

d3.jsはmike bostock氏による集計+SVG操作ツールです。
この投稿ではSVG操作は利用しません。

data = d3.csv.parse csvString

として、Object Arrayに変換し、その後、
coffeescript:
d3.nest().key((d)-> d.key).entries(data)

とするだけで、簡単にkeyでの集計を行うことができます。

また、タグの回数の集計などで利用したObjectも簡単に配列にすることができます。

d3.entries({"node.js": 32, "hadoop": 43}) 
# [{key: "node.js", value: 32}, {key: "hadoop", value: 43}]

ただ、こちらは、coffeeを利用している場合は、下記と等価な処理となります。

({ key: key, value: value} for key, value of {"node.js": 32, "hadoop": 43})

commander

commander.jsはTJによって開発された、コマンドラインのためのヘルパーモジュールです。

例えば引数としてファイルのパスを取るような場合は、下記のように記述するだけです。

fs = require 'fs'
commander = require 'commander'

program = commander.version('0.0.0')
  .parse(process.argv)

[filename] = program.args
program.help() unless filename

program.help()と書くと使い方を表示した上で、process.exitでプロセスを終了してくれます。

また、オプションを取るときには、次のように記述します。

fs = require 'fs'
commander = require 'commander'

program = commander.version('0.0.0')
  .option('-v,--verbose', 'url')
  .option('-u,--url <url>', 'url', String)
  .option('-o,--option [optional]', 'url', String)
  .parse(process.argv)

[filename] = program.args
url = program.url
program.help() unless filename or url

オプションの書き方は3種類あります。

  1. 引数なしのフラグ .option('-v, --verbose', 'description')
  2. 引数が必要なオプション .option('-u,--url <url>', 'url', String)
  3. 引数がオプショナルなオプション .option('-o,--option [optional]', 'url', String)

まとめ

2つのモジュールを利用することで、csvでもtsvでも、もちろん、JSONでも、簡単に取り込んで集計処理を書くことができます。

サンプル

例えば、アクセスログのCSV(これをどうやって入手したか、があれですが)が会ったとすると

fs = require 'fs'
commander = require 'commander'

program = commander.version('0.0.0')
  .parse(process.argv)

[filename] = program.args

program.help() unless filename

lines = d3.csv.parse fs.readFileSync filename, 'utf8'
d3.nest().key((d)-> d.status).entries lines
# [
#   { key: 200, values: [ {status 200の行が全部入ってる }] }
#   { key: 404, values: [ {status 404の行が全部入ってる }] }
#   { key: 500, values: [ {status 500の行が全部入ってる }] }
# ]


# 時間あたりのステータスの割合の場合は`.key()`をchainします。
lines = d3.csv.parse fs.readFileSync filename, 'utf8'
hour = d3.time.format("%Y%m%d%H0000")
d3.nest().key((d)-> hour(d.time)).key((d)-> d.status).entries lines
# [
#   { key: 20130524120000, values: [ 
#     { key: 200, values: [ {status 200の行が全部入ってる }] }
#     { key: 404, values: [ {status 404の行が全部入ってる }] }
#     { key: 500, values: [ {status 500の行が全部入ってる }] }
#   }
#   { key: 20130524130000, values: [ 
#     { key: 200, values: [ {status 200の行が全部入ってる }] }
#     { key: 404, values: [ {status 404の行が全部入ってる }] }
#     { key: 500, values: [ {status 500の行が全部入ってる }] }
#   }
#   { key: 20130524140000, values: [ 
#     { key: 200, values: [ {status 200の行が全部入ってる }] }
#     { key: 404, values: [ {status 404の行が全部入ってる }] }
#     { key: 500, values: [ {status 500の行が全部入ってる }] }
#   }
# ]

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
36