まだいまいち原因がよくわからんのだが、Mac OS X (Leopard) にあるsedにUTF-8の文字列を処理させるとやけに遅い。処理が終らん。
$ echo 'hogehoge:日本語 ' |\ sed -e 's/^\(.*\):\(.*\)<\/hoge>.*$/\1 \2/'
なんてやってみるとマジで処理が終らん。
しょうがないのでとりあえずMacPortsからGNU sedをインストールしてみた。
$ echo 'hogehoge:日本語 ' |\ gsed -e 's/^\(.*\):\(.*\)<\/hoge>.*$/\1 \2/' hogehoge 日本語
一瞬で終るっ!?!?
なんでやねーん。マルチバイト文字がダメなのか?
$ echo 'hogehoge:nihongo ' |\ sed -e 's/^\(.*\):\(.*\)<\/hoge>.*$/\1 \2/' hogehoge nihongo
うわ、一瞬で終る。やっぱマルチバイトか。
今度は一度euc-jpに変換してみる。
$ echo 'hogehoge:日本語 ' |\ nkf -e |\ sed -e 's/^\(.*\):\(.*\)<\/hoge>.*$/\1 \2/' |\ nkf -w hogehoge: 日本語
うわ一瞬で終った。けど処理されてねー。
Macのsedって*BSD由来だっけ? FreeBSDとかのsedもこんなんだっけっか。最近使ってないから知らないけど。AppleはUNIX認定とったりしてるわりにコマンドラインツールのメンテちゃんとやってくれてないなぅ。
とかなんとかつぶやいてたら師匠からアドバイスが。いつもいつもありがとうございます。
@koshian localeをLANG=Cにしたら高速になったりしない?
Twitter / JUN_Chan: @koshian localeをLANG=Cにしたら ...
いやそれも試したんだけどさあ……。
$ echo 'hogehoge:日本語 ' |\ LANG=C sed -e 's/^\(.*\):\(.*\)<\/hoge>.*$/\1 \2/'
ほら、やっぱり変わらず……。ん、まてよ。
$ echo 'hogehoge:日本語 ' |\ LC_ALL=C sed -e 's/^\(.*\):\(.*\)<\/hoge>.*$/\1 \2/' hogehoge 日本語
うわ、一瞬で終った。LANGじゃなくてLC_*のどれかってことか……。
なんでこうなるのかまだよくわかんないなあ。Macのsedがどこ由来のものか調べるところからか。
とりあえずめんどうならGNU sed使っとけ、というのもアレだしなあ。
追記
いくつか情報を頂いた。
たぶん影響しているのは LC_COLLATE and/or LC_CTYPE だと思います。 locale を C (POSIX) 以外にすると桁違いに遅くなるというのは GNU grep でも 散々レポートされてたりするのですが、Mac OS X の sed はどういうつくりになっているのか。 Slow Unix terminal commands - The macosxhints Forums 基本的にはある locale のエンコーディングの文字列を wide char の string に変換するところがちょっとね。という話なんですが。
エンコーディングを EUC-JP に変えたらすぐ終わったけどなにも変わってないというのは、 locale 設定が UTF8 のままなので EUC-JP での文字列を不正なバイト列として スキップしたからじゃないかと思います。
ときどきの雑記帖 i戦士篇 2009年7月(上旬)
残念ながらLC_COLLATEもLC_CTYPEでもないようで、ちゃんとソースおっかけないとみたいです。マルチバイト対応するとどうしても遅くなるんですかねえ。
はてなブックマーク - Mac OS Xのsedがみょーに遅い件 - 狐の王国
- otsune マルチバイトで遅いのは既知の問題で昔からリポートされてる。だからperl使った方が速い。 2009/07/05
- m-bird 言及 FreeBSD6.4-Rですが、一瞬で終わりますよ。LANG,LC_ALLともにja_JP.UTF-8です。// LC_ALLをCにするのは、subversionで文字化けでどうしようも無くなった時とかだなあ。。。 2009/07/03
とのこと。FreeBSDでは問題無し、Macのsedが遅いのは既知ってことか。んー、このへんてどこでバグレポート見れるんだろう。
Appleのこのへんのソースコードがさっぱり見付けられないのはどういうわけか。どっかにはあるんだろうけど、もちょっと分かりやすいところに置いて欲しいなあ……。