neu*_*242 1 php unicode macos utf-8 unicode-normalization
我正在创建一个非常简单的文件搜索,其中搜索数据库是一个文本文件,每行一个文件名。数据库是使用 PHP 构建的,并通过 grep 文件(也使用 PHP)找到匹配项。
\n\n这在 Linux 中效果很好,但在使用非 ascii 字符时则不适用于 Mac。看起来 HFS+ (MacOSX) 上的名称编码与 ext3 (Linux) 上的名称编码不同。这是一个 test.php:
\n\n<?php\n$mystring = "abc\xc3\xb3\xc3\xbc\xc3\x9adef\xc3\xa5";\nfile_put_contents($mystring, "");\n$h = dir(\'.\');\n$h->read(); // "."\n$h->read(); // ".."\n$filename = $h->read();\n\nprint "string: $mystring and filename: $filename are ";\n\nif ($mystring == $filename) print "equal\\n";\nelse print "different\\n";\nRun Code Online (Sandbox Code Playgroud)\n\n运行 MacOSX 时:
\n\n$ php test.php\nstring: abc\xc3\xb3\xc3\xbc\xc3\x9adef\xc3\xa5 and filename: abc\xc3\xb3\xc3\xbc\xc3\x9adef\xc3\xa5 are different\n$ php test.php |cat -evt\nstring: abc\xc3\xb3\xc3\xbc?M-^Zdef\xc3\xa5$ and filename: abco?M-^Au?M-^HU?M-^Adefa?M-^J are different$\nRun Code Online (Sandbox Code Playgroud)\n\n在 Linux 上运行时(或在 MacOSX 上安装 nfs 的 ext3 文件系统上):
\n\n$ php test.php\nstring: abc\xc3\xb3\xc3\xbc\xc3\x9adef\xc3\xa5 and filename: abc\xc3\xb3\xc3\xbc\xc3\x9adef\xc3\xa5 are equal\n$ php test.php |cat -evt\nstring: abcM-CM-3M-CM-<M-CM-^ZdefM-CM-% and filename: abcM-CM-3M-CM-<M-CM-^ZdefM-CM-% are equal$\nRun Code Online (Sandbox Code Playgroud)\n\n有没有办法让这个脚本在两个平台上返回“相等”?
\nMacOSX 使用规范化形式 D (NFD) 来编码 UTF-8,而大多数其他系统使用 NFC。

NFD 到 NFC 转换有多种 实现方式。在这里,我使用 PHP Normalizer 类来检测 NFD 字符串并将其转换为 NFC。它在 PHP 5.3 中或通过PECL 国际化扩展提供。以下修改将使脚本正常工作:
...
$filename = $h->read();
if (!normalizer_is_normalized($filename)) {
$filename = normalizer_normalize($filename);
}
...
Run Code Online (Sandbox Code Playgroud)