在PHP中比较两个Unicode字符串

3

我在 PHP 中比较两个包含特殊字符 'ö' 的 Unicode 字符串时遇到了困难。一个字符串来自 $_GET,另一个是文件系统的文件夹名称(scandir())。这两个字符串在我的看法下似乎是相等的,但实际上却不相等。

var_dump($filter);
var_dump($tail . '/' . $k);

在它们上面也显示了它们的相等性,但是有不同的字符串长度(?!):

string '/blöb' (length=7)
string '/blöb' (length=6)

以下是我的代码片段来比较它们:

if($filter == ($tail . '/' . $k)) {
    /* ... */
}

这里发生了什么? 额外信息:$tail是一个空字符串:
string '' (length=0)

在你的两种情况下,print_r(unpack("H*",$k)) 返回什么? - Anders Lindahl
请记住,某些文件系统使用NFD(或接近NFD),而您可能正在考虑NFC。如果要进行二进制比较,则需要将其规范化为相同的内容。但是,在文本上进行二进制比较是不明智的。您需要使用UCA进行文本比较。请参阅我在OSCON上的Unicode七种语言演讲 - tchrist
2个回答

3
请看这里:http://en.wikipedia.org/wiki/Unicode_equivalence,并使用这个:http://www.php.net/manual/en/class.normalizer.php 你可能在较长的字符串中有一个分解字符,这意味着一个 o 和一个叠加的 umlaut 组合字符覆盖了前一个字符。
规范化函数将修复这样的问题。
顺便提一下,如果您将输入用于等价性(例如用户名),则应始终对其进行规范化,即使字符串的二进制表示不同,也要确保两个人不选择相同的用户名。

这个答案需要安装 intl。所以如果你已经安装了,为什么不使用 collator_compare 呢?我正在寻找一个不使用 intl 的答案... - user9645
@user9645,所以您想处理Unicode字符串,包括它们的巨大复杂性,而不实际安装知道如何处理Unicode的库?我不认为这是可能的。 - Ariel
Ariel - 不,我只是想要一个替代GNU intl的选择。就这样。 - user9645
@user9645 intl不是GNU,它来自ICU库(最初由Talligent和IBM编写,然后由Sun接手),这是*定义性的Unicode库,实际上是Unicode的一部分。现在没有人再使用其他任何东西了。您可以尝试iconvuconv,但我认为它们无法做到这一点,并且也不再维护。您能告诉我为什么要避免intl吗? - Ariel

-1

感谢您回答我的问题。我投票支持您。 - Naeem Ul Wahhab

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接