2011/11/24


日本語を扱っていて困るのがgrep。正規表現パターンにマルチバイト文字を混ぜられなかったり、windowsで動かすと"表"の様に2バイト目にbackslashが混じる文字で動作しなくなったりします。
さらに複数のエンコーディングで書かれたファイルが散らばっていると一度のgrepで検索出来なかったりもします。
vimに限っては、内蔵のvimgrepを使う事で解決出来ますが、見つかったファイルをバッファに開いてしまうという挙動がある為、grepオリジナルの動作を求めている人にとっては都合の悪い物だったりもします。

vimgrepの様に複数のエンコーディングに対応していて、検索パターンにマルチバイト文字を含んだ正規表現が使えて、windowsでもちゃんと動いて、ついでといっちゃあなんだが、"**/*.txt"で再帰検索してくれる様なgrep無いかなぁと思ってたんですが、やっぱり無いので作りました。
こういう処理、実はGo言語が得意でして、意外と短いコードで書けてしまったりします。
もちろんバイナリが吐けるので配布も簡単。
mattn/jvgrep - GitHub

grep for japanese vimmer

https://github.com/mattn/jvgrep
内部ではgo-iconvという、元々別の方が作ったiconvモジュールをwindowsでダイナミックローディング対応させ使っています。もちろんスタティックリンクなので別途調達する必要もありませんが。なお、windows上での動作にはiconv.dllかlibiconv.dllが必要です。
Go言語の開発環境を持っていらっしゃる方ならば、最新までバージョンを上げて頂いた後 # goinstall github.com/mattn/jvgrep
として頂いたらインストールしてくれます。go-iconvが依存物としてインストールされますが、linux等ではiconvのヘッダおよびライブラリが必要になりますので注意です。windowsはダイナミックローディングしているので必要ありません。
ちなみに、win32版のみ最新版のjvgrepをダウンロード出来る様にしてあります。上記リンクから"Downloads"をクリックして"jvgrep-win32.tar.gz"を落とし、解凍して下さい。iconv.dllを同梱しています。ウィルスチェック済み。

使い方は普通のgrepです。 # jvgrep 表[現示] *.txt
この様に日本語で、しかもwindowsだと誤動作するダメ文字にも対応しています。
まぁGo言語は内部では全てutf-8なので、当たり前ですが。
尚、Goのregexpパッケージがまだ発達途上なので":alpha:"の様な文字クラスは使えません。使いたい人は今すぐGo Developer Teamに参加してpatchを書いて下さい。(使える様になりました)

vimmer向けに # jvgrep 表[現示] **/*.txt
という使い方も出来ます。 オプションは現状ありません。出力結果はgrepで"-n"オプションを付けた時の出力内容に合わせてあります。
サポートしているエンコーディングは
  • iso-2022-jp-3
  • iso-2022-jp
  • euc-jisx0213
  • euc-jp
  • utf-8
  • ucs-bom
  • euc-jp
  • eucjp-ms
  • cp932
と、ほぼ全ての日本人向けエンコーディングに対応出来ています。
仕組みはvimと同じです。 vimからは set grepprg=jvgrep
とvimrcに書けば使えます。
:grep 表[現示] **/*.txt
といった感じにお使い下さい。
Posted at by



2011/08/04


最近はクラウドサーバ等、割と色んな所で見かける様になったuWSGIですが...
uWSGI

uWSGI is a fast, self-healing and developer/sysadmin-friendly application container server coded in pure C.

http://projects.unbit.it/uwsgi/
Perlだとhirataraさんが書いた記事や
Hokkaido.pmでuWSGIについてLTした - a geek born in Tomakomai

uWSGI はデフォルトではhttpではなくuwsgiプロトコルを喋るので、uwsgiプロトコルを喋れるフロントエンドを立ち上げます...

http://d.hatena.ne.jp/hiratara/20110718/1310950381
Plack::App::uWSGIが参考になります。
hiratara/p5-Plack-App-uWSGI - GitHub

Plack::App::uWSGI - a PSGI frontend of uwsgi.

https://github.com/hiratara/p5-Plack-App-uWSGI
こちらはuwsgiに付属のpsgiプラグインを使っています。なお、uwsgiのcontribフォルダにはPlack::Handler::Uwsgiが同梱されているので、例えばnginx.confに server {
  listen 8082;
  location / {
    include uwsgi_params;
    uwsgi_pass 127.0.0.1:9999;
  }
}
と書いておき use Plack::Handler::Uwsgi;

my $app = sub {
    return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'Hello World' ] ];
};
Plack::Handler::Uwsgi->new(host=>'127.0.0.1'port=>9999)->run($app)
こんな感じに走らせると、"http://server:8082/" で"Hello World"が表示されます。もちろんフロントエンドであるnginxの設定を弄ればキャッシュやタイムアウトも変更出来るという仕組みです。

ちなみにcontribフォルダにはrubyやjavaのコードも置いてあります。つまりuWSGIプロトコルを実装すれば、言語を問わずフロントエンドをnginxとしたワーカーが作れるって事ですかね。

Go言語も仲間に入れてよ!って事でuWSGIリスナを書いてみました。
mattn/go-uwsgi - GitHub

uwsgi implement for go

https://github.com/mattn/go-uwsgi
あくまでリスナという位置づけなので、unixドメインソケットのファイルや、tcpソケットなど、goでnet.Listenerとして扱える物であれば何でもokです。これを使うとファイルサーバがほんの数行で書けてしまいます。

nginx.confが server {
  listen 8081;
  location / {
    include uwsgi_params;
    uwsgi_pass unix:///var/run/go-uwsgi/socket;
  }
}
であれば package main

import (
    "net"
    "http"
    "github.com/mattn/go-uwsgi"
    "os"
)

func main() {
    s := "/var/run/go-uwsgi/socket"
    os.Remove(s)
    l, e := net.Listen("unix", s)
    if e != nil { panic(e.String()) }
    http.Serve(&uwsgi.Listener{l}, http.FileServer(http.Dir(".")))
}
これだけですね。簡単です。
初めてのPerl 第5版 初めてのPerl 第5版
Randal L. Schwartz, Tom Phoenix, brian d foy, 近藤 嘉雪
オライリージャパン 大型本 / ¥486 (2009年10月26日)
 
発送可能時間:

Posted at by



2011/07/14


GoogleのGo 節電 プロジェクトが全然Go言語に関係なくて悲しかったので、本日公開されたGo節電プロジェクトAPIを叩くインタフェースライブラリを書いた。
mattn/go-setsuden - GitHub

interface to gosetsuden API.

https://github.com/mattn/go-setsuden
使い方はexampleフォルダにある物を参照下さい。
package main

import "github.com/mattn/go-setsuden"

func main() {
    println("■東京の最新計測値")
    pu, _ := setsuden.GetActualUsage("tokyo")
    for _, p := range pu {
        println("時間", p.Datetime)
        println("間隔", p.Duration)
        println("値 ", p.Value)
    }
    println()

    println("■東京の最新予測値")
    pu, _ = setsuden.GetEstimatedUsage("tokyo")
    for _, p := range pu {
        println("時間", p.Datetime)
        println("間隔", p.Duration)
        println("値 ", p.Value)
    }
    println()

    println("■東京の最新瞬時値")
    pu, _ = setsuden.GetInstantUsage("tokyo")
    for _, p := range pu {
        println("時間", p.Datetime)
        println("間隔", p.Duration)
        println("値 ", p.Value)
    }
    println()

    println("■東京の電力供給ピーク値")
    pp, _ := setsuden.GetPeakOfSupply("tokyo")
    for _, p := range pp {
        println("開始", p.Start)
        println("終了", p.End)
        println("値 ", p.Value)
    }
    println()

    println("■東京の電力供給ピーク予想値")
    pp, _ = setsuden.GetPeakOfDemand("tokyo")
    for _, p := range pp {
        println("開始", p.Start)
        println("終了", p.End)
        println("値 ", p.Value)
    }
    println()
}
さっき実行したらこんな感じでした。
■東京の最新計測値
時間 2011-07-14T10:00:00+09:00
間隔 3600
値  43480000

■東京の最新予測値
時間 2011-07-14T19:00:00+09:00
間隔 3600
値  41580000

■東京の最新瞬時値
時間 2011-07-14T11:25:00+09:00
間隔 300
値  44360000

■東京の電力供給ピーク値
開始 2011-07-14T09:00:00+09:00
終了 2011-07-14T20:00:00+09:00
値  52700000

■東京の電力供給ピーク予想値
開始 2011-07-14T14:00:00+09:00
終了 2011-07-14T15:00:00+09:00
値  45500000

Go言語、全然関係無いですね!
Posted at by