web-dev-qa-db-fra.com

Comparaison de chaînes insensible à la casse

Je voudrais comparer deux variables pour voir si elles sont identiques, mais je veux que cette comparaison soit insensible à la casse.

Par exemple, ce serait sensible à la casse:

if($var1 == $var2){
   ...
}

Mais je veux que ce soit insensible à la casse, comment pourrais-je aborder cela?

61
Deniz Zoeteman

C'est assez simple; il vous suffit d'appeler strtolower() sur les deux variables.

Si vous devez gérer des jeux de caractères Unicode ou internationaux, vous pouvez utiliser mb_strtolower() .

Veuillez noter que d'autres réponses suggèrent d'utiliser strcasecmp() - cette fonction ne gère pas les caractères multi-octets, donc les résultats pour toute chaîne UTF-8 sera faux.

100
asthasr

strcasecmp() renvoie 0 si les chaînes sont les mêmes (sauf les variations de casse), vous pouvez donc utiliser:

if (strcasecmp($var1, $var2) == 0) {
}
66
Ramon

Si votre chaîne est codée sur un seul octet, c'est simple:

if(strtolower($var1) === strtolower($var2))

Si votre chaîne est UTF-8, vous devez considérer la complexité d'Unicode: en minuscules et en majuscules ne sont pas des fonctions bijectives, c'est-à-dire si vous avez un caractère en minuscules, transformez-le en majuscules et transformez en minuscule, vous ne pouvez pas vous retrouver avec le même point de code (et il en va de même si vous commencez par un caractère majuscule).

Par exemple.

  • "İ" (Latin Capital Letter I with Dot Above, U+0130) Est un caractère majuscule, avec "i" (Latin Small Letter I, U+0069) Comme variante minuscule - et la variante majuscule "i" est "I" (Latin Capital Letter I, U+0049).
  • "ı" (Latin Small Letter Dotless I, U+0131) est un caractère minuscule, avec "I" (Latin Capital Letter I, U+0049) comme variante majuscule - et la variante minuscule "I" est "i" (Latin Small Letter I, U+0069)

Donc mb_strtolower('ı') === mb_strtolower('i') retourne false, même s'ils ont le même caractère majuscule. Si vous voulez vraiment une fonction de comparaison de chaînes insensible à la casse, vous devez comparer avec les majuscules ET la version minuscule:

if(mb_strtolower($string1) === mb_strtolower($string2)
  || mb_strtoupper($string1) === mb_strtoupper($string2))

J'ai exécuté une requête sur la base de données Unicode de https://codepoints.net ( https://dumps.codepoints.net ) et j'ai trouvé 180 codes point pour lequel j'ai trouvé un caractère différent en prenant les minuscules des majuscules des caractères minuscules, et 8 point de code pour lequel j'ai trouvé un caractère différent lors de la prise des majuscules des minuscules des caractères majuscules

Mais ça empire : le même cluster de graphèmes vu par l'utilisateur, peut avoir plusieurs façons de l'encoder: "ä" peut être représenté par la fonction Latin Small Letter a with Diaeresis (U+00E4) ou comme Latin Small Letter A (U+0061) et Combining Diaeresis (U+0308) - et si vous les comparez au niveau d'un octet, cela ne retournera pas vrai!

Mais il existe une solution pour cela en Unicode: Normalisation ! Il existe quatre formes différentes: NFC, NFD, NFKC, NFKD. Pour la comparaison des chaînes, NFC et NFD sont équivalents et NFKC et NFKD sont équivalents. Je prendrais NFKC car il est plus court que NFKD, et "ff" (Latin Small Ligature ff, U+FB00) Sera être transformé en deux "f" normaux (mais 2⁵ sera également étendu à 25…).

La fonction résultante devient:

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);
}

Notez s'il vous plaît:

  • vous avez besoin du paquet intl pour le Normalizer
  • vous devez optimiser cette fonction en vérifiant d'abord si elles sont juste égales ^^
  • vous voudrez peut-être utiliser NFC au lieu de NFKC, car NFKC supprime trop de distinctions de formatage à votre goût
  • vous devez décider par vous-même, si vous avez vraiment besoin de toute cette complexité ou si vous préférez une variante plus simple de cette fonction
14
Beat
if(strtolower($var1) == strtolower($var2)){
}
1
Shakti Singh

Utilisez strcasecmp .

0
Oswald