不区分大小写的字符串比较

Den*_*man 65 php if-statement case-insensitive

我想比较两个变量,看它们是否相同,但我希望这个比较不区分大小写.

例如,这将区分大小写:

if($var1 == $var2){
   ...
}
Run Code Online (Sandbox Code Playgroud)

但是我希望这个不区分大小写,我该如何处理呢?

ast*_*asr 105

这很简单; 你只需要调用strtolower()两个变量.

如果需要处理Unicode或国际字符集,可以使用mb_strtolower().

请注意,其他答案建议使用strcasecmp()-that函数不处理多字节字符,因此任何UTF-8字符串的结果都将是假的.

  • 对不起,我不是MySQL的专家; 您可能希望将其作为单独的问题发布. (4认同)
  • 不幸的是,这并不是那么简单:在Unicode中,小写变体的大写字母可能不一样,就像你开始时一样 - 反之亦然.即你必须与mb_strtolower()和mb_strttoupper()进行比较. (4认同)

Ram*_*mon 66

strcasecmp() 如果字符串相同则返回0(除了大小写变化),因此您可以使用:

if (strcasecmp($var1, $var2) == 0) {
}
Run Code Online (Sandbox Code Playgroud)

  • `strcasecmp()`不处理多字节字符,因此无法处理Unicode. (5认同)
  • 只记得测试== 0; 这是违反直觉的,因为写"if(strcasecmp($ var1,$ var2)){..."非常诱人,但在这种情况下,0意味着相等而不是假注意等等. (3认同)

Bea*_*eat 14

如果你的字符串是单字节编码,那很简单:

if(strtolower($var1) === strtolower($var2))
Run Code Online (Sandbox Code Playgroud)

如果你的字符串是UTF-8,你必须考虑Unicode的复杂性:to-lower-case和to-upper-case不是双射函数,即如果你有一个小写字符,把它转换成大写字母,然后转换它回到小写,你可能不会得到相同的代码点(如果你以大写字母开头也是如此).

例如

  • "İ"(Latin Capital Letter I with Dot Above, U+0130)是一个大写字符,"i"(Latin Small Letter I, U+0069)作为它的小写变体 - 而"i"的大写变体是"I"(Latin Capital Letter I, U+0049).
  • "ı"(Latin Small Letter Dotless I, U+0131)是一个小写字符,"I"(Latin Capital Letter I, U+0049)作为其大写变体 - 而"I"的小写变体是"i"(Latin Small Letter I, U+0069)

所以mb_strtolower('?') === mb_strtolower('i')返回false,即使它们具有相同的大写字符.如果你真的想要一个不区分大小写的字符串比较函数,你必须比较大写和小写版本:

if(mb_strtolower($string1) === mb_strtolower($string2)
  || mb_strtoupper($string1) === mb_strtoupper($string2))
Run Code Online (Sandbox Code Playgroud)

我从https://codepoints.net ( https://dumps.codepoints.net)运行了一个针对Unicode数据库的查询,我找到了180个代码点,当我采用小写字符时,我发现了一个不同的字符大写字母的小写字母和8个代码点,当我用大写字母的小写字母大写字母时,我发现了一个不同的字符

但它变得更糟:用户看到的相同的字形集群可能有多种编码方式:"ä"可以表示为Latin Small Letter a with Diaeresis (U+00E4)或作为Latin Small Letter A (U+0061)Combining Diaeresis (U+0308)- 如果你在字节级别比较它们,这将不会返回true!

但是在Unicode中有一个解决方案:规范化!有四种不同的形式:NFC,NFD,NFKC,NFKD.对于字符串比较,NFC和NFD是等效的,NFKC和NFKD是等效的.因为它比NFKD短,我会选择NFKC,并且"ff"(Latin Small Ligature ff, U+FB00)将转换为两个正常的"f"(但是2⁵也会扩展到25 ......).

结果函数变为:

function mb_is_string_equal_ci($string1, $string2) {
    $string1_normalized = Normalizer::normalize($string1, Normalizer::FORM_KC);
    $string2_normalized = Normalizer::normalize($string2, Normalizer::FORM_KC);
    return mb_strtolower($string1_normalized) === mb_strtolower($string2_normalized)
            || mb_strtoupper($string1_normalized) === mb_strtoupper($string2_normalized);
}
Run Code Online (Sandbox Code Playgroud)

请注意:

  • 你需要用于Normalizerintl
  • 你应该首先检查它们是否相等^^来优化这个功能
  • 您可能希望使用NFC而不是NFKC,因为NFKC会根据您的喜好去除太多的格式区别
  • 你必须自己决定,如果你真的需要所有这些复杂性,或者你更喜欢这个功能的简单变体