
大仰なタイトルですが、約1年前の記事「PHPのsort関数は相当おかしい」の補足記事です。僕が何を根拠にPHPのsort関数(の第二引数のデフォルト値)がおかしいと思ったかを説明します。一言でいうと、PHPの全ての値とSORT_REGULAR(言い換えるとPHPの<、==、>)の組み合わせが全順序集合になっていないからです。
PHPのsort関数は第二引数で比較演算子を変更できますが、省略するとSORT_REGULARを用います。これはPHPの通常の比較演算子と同じ挙動で、両辺の値が数字っぽい場合は数値として、そうでなければ文字列として比較するものです。このような比較を用いると、ソートが不可解な挙動を示すことがあります。
$ php -r '$a=array("0xa","011","01a","2.0");sort($a);print_r($a);sort($a);print_r($a);'
Array
(
[0] => 2.0
[1] => 0xa
[2] => 011
[3] => 01a
)
Array
(
[0] => 01a
[1] => 2.0
[2] => 0xa
[3] => 011
)
4つの文字列をソートして、その結果を更にソートする、という例を作ってみました。1回目のソート結果では最大だった値"01a"が再度ソートすると最小になっています。これは大抵の人には予測不可能な挙動であり、挙動が予測可能なSORT_NUMERICまたはSORT_STRINGを明示的に指定すべきだ、というのが前回記事の趣旨でした。
では、なぜSORT_REGULARは不思議な動きをするのでしょうか。また、SORT_NUMERICやSORT_STRINGにすると何が変わるのでしょうか。これを説明する上で重要なのが、最初に挙げた「全順序集合」です。

年末の恒例行事ということで、2009年のまとめ記事です。
2009年は本記事を含め43本の記事を書きました。人気があったのは下記の記事です。また、今年は12ヶ月記事が揃いました。毎月1本以上記事が書けたのは初めてです。
sortの記事はarray_uniqueの件の前フリだったんですが、オヤジギャグのせいか大人気でした。
会社ブログには13本の記事を書きました。こちらはここ半年くらいサボってますね…。きっと来年は真面目にやります。

テキストファイルの末尾に改行がたくさんついてたり、逆に1個もついていなかったりすることってありますよね。たくさんあるファイルについて、末尾改行1個だけの形に統一したいなー、と思ったら意外と苦労したので紹介します。
本当はもっとシンプルに書けそうな気もするんですが…。
perl -i.bak -pe 'BEGIN{undef $/}s/([^\n])\n*$/$1\n/;' hoge.txt
ポイントは「undef $/」です。$/は入力の区切り文字を意味し、デフォルトでは改行文字となっています。これを未定義値にすると、1行を取得しようとしてファイル全体を取得するので、改行を跨いだ置換が可能になります(ファイルが巨大なときには死にかねませんが、手元で作業する分にはいいでしょう)。
ただ、改行を含む文字列の置換ははまりどころが多いので注意が必要です。僕だけかもしれませんが、毎度のことなのにsフラグとmフラグについて混乱したりします。今回の例ではmをつけるとうまく動きませんが、普段はmフラグの付け忘れで混乱するように思います。「man perlre」を参照してください。
これをxargsで回せば作業は完了ということになります。
find . -name '*.txt' | xargs perl -i.bak -pe 'BEGIN{undef $/}s/([^\n])\n*$/$1\n/;'
(追記:2009/12/27 11:40)また、*.phpのファイル末尾の「?>」を、前後の余計な空白文字列ごと削りたい場合は次のように書けます。「?>」以降に余計な改行が含まれていて困る、なんて場合に便利かと思います。
find . -name '*.php' | xargs perl -i.bak -pe 'BEGIN{undef $/}s/\s*\?\>\s*$/\n/;'

補足:Email::MIMEについては「モダンPerlの世界へようこそ:第20回 Email::Sender:メールを送信する|gihyo.jp … 技術評論社」の内容とかぶってました…。この記事によればEmail::Senderも既に安定してるみたいなので、Email::Sendを使っている本記事の内容はあまり意味がない気がします。
久々にPerlの話題です。「メールの送信 - モダンなPerl入門」にある通り、最近はEmail::MIME+Email::Sendでメールを送るのが流儀なんだそうです。*1
しかし、まだまだPerl使いの中でもモダンすぎるせいか、ネットを探しても利用例が少ない気がしました。特に、Gmailからメール送信したい場合にはEmail::Send::SMTPでSSLまたはTLS認証を利用することになるんですが、その実例となると皆無に近い気がしましたので、そのあたりをまとめてみました。
*1:「Email::SendじゃなくてEmail::Senderを使えと言われても - soffritto::journal」によれば、Email::Sendもoldtypeになりつつあるようですが…

PHP5.3.0から実装されたSplFixedArrayというSPLクラスがあります。これはマニュアルによれば下記のようなクラスです。
SplFixedArray クラスは配列の主要な機能を提供します。 SplFixedArray と通常の PHPの配列との主な違いは、 SplFixedArray は固定長であって、整数値で指定した範囲内の添字しか使用できないところです。これにより、より高速な配列の実装が可能となりました。
制限はあるけれども高速な配列もどきのクラスだと紹介してありますね。このクラスについて少し調べてみました。
まずはSplFixedArrayが本当に速いのかどうか、下記のようなプログラムで実験してみました。実験はPHP5.3.0で行いました。