NFDで正規化されたUnicode文字列(Macの日本語ファイル名など)をPHPでNFCで正規化し直す方法 #php #mac version 4

2016/07/30 00:42 by hiro_y hiro_y
  :追加された部分   :削除された部分
(差分が大きい場合、文字単位では表示しません)
NFDで正規化されたUnicode文字列(Macの日本語ファイル名など)をPHPでNFCで正規化し直す方法 #php #mac
ウノウラボに[「Mac OS X上のUnicode」](https://unoh.github.io/2007/09/04/unicode-on-mac.html)を書いたのが、もう9年も前。相変わらずMacの日本語ファイル名はNFDで正規化されたUnicodeで、そのままだとPHPのmbstringなどで扱えない。濁点、半濁点が含まれる文字列が途中で切れてしまったりする。

当時書いた記事では次のように「PHP6が待ち遠しい」と書いたが、結局PHP 6は出ずにPHP 5.3にバックポートされたのはご存知の通り。

> ICUを使った正規化ライブラリが存在するようなので、 ICUベースでUnicode対応する予定のPHP6が待ち遠しいところです。

PHP 5.3から[ICUのライブラリを使ったNormalizerクラス](http://php.net/manual/ja/class.normalizer.php)が組み込まれたので、それを使えばPHPで簡単に正規化し直せるようになった。

```php
if (\Normalizer::isNormalized($input, \Normalizer::FORM_D)) {
    $input = Normalizer::normalize($input, \Normalizer::FORM_C);
if (Normalizer::isNormalized($input, Normalizer::FORM_D)) {
    $input = Normalizer::normalize($input, Normalizer::FORM_C);
}
```

ちなみに`Normalizer::FORM_C`の代わりに`Normalizer::NFC`、`Normalizer::FORM_D`の代わりに`Normalizer::NFD`でも定数が定義されているので使える模様(マニュアルには記載なし)。      

ウノウラボに「Mac OS X上のUnicode」を書いたのが、もう9年も前。相変わらずMacの日本語ファイル名はNFDで正規化されたUnicodeで、そのままだとPHPのmbstringなどで扱えない。濁点、半濁点が含まれる文字列が途中で切れてしまったりする。

当時書いた記事では次のように「PHP6が待ち遠しい」と書いたが、結局PHP 6は出ずにPHP 5.3にバックポートされたのはご存知の通り。

ICUを使った正規化ライブラリが存在するようなので、 ICUベースでUnicode対応する予定のPHP6が待ち遠しいところです。

PHP 5.3からICUのライブラリを使ったNormalizerクラスが組み込まれたので、それを使えばPHPで簡単に正規化し直せるようになった。

if (Normalizer::isNormalized($input, Normalizer::FORM_D)) {
    $input = Normalizer::normalize($input, Normalizer::FORM_C);
}

ちなみにNormalizer::FORM_Cの代わりにNormalizer::NFCNormalizer::FORM_Dの代わりにNormalizer::NFDでも定数が定義されているので使える模様(マニュアルには記載なし)。