2016年12月1日 : してログ

PCRE 修飾子で「s」を指定した場合「ドットメタ文字は改行を含むすべての文字にマッチします」、「 これを設定しない場合は、改行にはマッチしません」とあります。例えば「/^(.+)$/m」のように書けば、複数行テキストを配列に取ることができるはずなのですが、実際やってみると改行を含むテキストが返ってきます。対処法で trim を掛けたりしていましたが、せっかくなので調べてみました。

改行の意味するもの

改行の種類として「LF」「CR+LF」「CR」の3種類があると思いますが、実際にテストコードを書いてみたところ、ドットメタ文字は「CR」にマッチし「LF」にマッチしませんでした。マニュアルには単に「改行」と書かれているので、これらのすべてに対応しているものと思い込んでおりましたが、違うようです。従って、上の例で改行に見えていたのは「CR+LF」の「CR」が残っていたものと思われます。

改行を配列に取る正しい例

原因が分かれば話は簡単で、文字クラスの否定を使って「CR」及び「LF」を指定すれば良いだけです。

preg_match_all('/[^\r\n]+/m', $text, $match);
まとめ

マニュアルなどで単に「改行」と言った場合は「LF」のみを指すと思って良さそうです。プログラム書くときも特に意識しないで "\n" を使ってますし、UNIX 系では「LF」なのだから当然と言えば当然でした。毎回悩むのもアレなので、改行テキストを綺麗な配列に取る関数を自作しておくと楽かも知れません。

要注意なのは、HTML の改行コードが「CR+LF」で規定されている点です。このため、textarea で POST されたデータは「CR+LF」になっており、取り扱う際に注意しなければなりません。また、PHP などで HTML を出力する際の改行コードを「LF」のみとしてしまうのは、本来間違いということになります(今まで結構やってたなあ)。多くの場合、「LF」で出力しても、「CR+LF」「LF」が混在していてもブラウザの表示には影響しませんが、気になる方は HTML は「CR+LF」と覚えておくといいかも知れません。