文字エンコーディングと正規表現
PHPの文字エンコーディング
- ISO-2022-JP
日本語Eメールでよく使われる。
- Shift_JIS(CP932)
古いガラケーでも使える文字コード。プログラムやDBでの設定は非推奨なので注意すべし。
- EUC-JP
昔プログラムやDBで使われていた文字コードだが、今はutf-8にその座を奪われている。
日本語だけでなくアジア圏、ヨーロッパ圏でも使われる文字エンコードで今はこれが主流だったりする。
ので、新規案件はutf-8に指定するのが望ましい。
の3つ。HTMLはともかく、プログラムやDBの文字エンコードは統一しないとトラブルのもとになる。
日本語の文字列を扱うPHP関数として、iconvとmbstringがあるが、
iconvはPHP同梱ではなく環境に依存してしまうため、現在でもメンテナンスが続けられていて
PHPに同梱されているmbstringを使うことが推奨される。
最長一致に気をつけるべし
正規表現を使って、
<a name="bar">bar</a>
という結果を出したいとき、どうしたらよいのか?
<?php $html='<a href="#foo">foo</a><a name="bar">bar</a>'; preg_match('/<a.*>bar<\/a>/', $html, $matches); var_dump($matches[0]); ?>
結果は次のようになる。
string(43) "<a href="#foo">foo</a><a name="bar">bar</a>"
最長一致といっても、どこのアンカータグなのかを指定しきれていないので、
上記のような結果になってしまったと考えらる。
ちなみに、最短一致を利用しても、
<?php $html='<a href="#foo">foo</a><a name="bar">bar</a>'; preg_match('/<a.*?>bar<\/a>/', $html, $matches); var_dump($matches[0]); ?>
同じ結果となる。
string(43) "<a href="#foo">foo</a><a name="bar">bar</a>"
最短一致を利用しても、どこのアンカータグなのか分からないから。
欲しい検索結果を出したいときは、このように書くと良いようだ。
<?php $html='<a href="#foo">foo</a><a name="bar">bar</a>'; preg_match('/<a[^>]*>bar<\/a>/', $html, $matches); var_dump($matches[0]); ?>
結果はこのようになった。
string(21) "<a name="bar">bar</a>"
'>' まで読み進めるのに '>' 以 外の文字の 0 回以上繰り返しと書くことが肝要なようだ。
上記2つだと、ずっと先までアンカータグを検索してしまうらしい。
正規表現関数の選択
バイナリセーフではないため、ereg関数は推奨できない。
PCRE関数はPHP同梱ではないため、環境に依存する。
また、日本語文字列を正規表現させたい場合は、
u修飾子を使う(ただし、utf-8サポートなしでライブラリがコンパイルされていた場合、u修飾子も使えないことは注意すべし)
mb_ereg関数(マルチバイト正規表現関数)
mbstringエクステンションの一部(PHPに同梱されている)
多くの文字エンコーディングに対応している「鬼車」を使っている。
ただ、mb_ regex_encoding関数で正規表現および検索対象文字列の文字エンコーディングを指定する
必要がある。指定しないと環境によっては別のエンコーディングで正規表現を始めてしまう事もある。
また、正規表現パターンはシングルクォートで囲むのが望ましい。
(ダブルクォートよりは混乱が減る)