web-dev-qa-db-ja.com

大文字と小文字を区別しない文字列比較

2つの変数を比較して同じかどうかを確認したいのですが、この比較では大文字と小文字を区別しません。

たとえば、これは大文字と小文字が区別されます。

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

しかし、これは大文字と小文字を区別しないようにしたいのですが、これにどのようにアプローチしますか?

61
Deniz Zoeteman

これはかなり簡単です。両方の変数で strtolower() を呼び出すだけです。

Unicodeまたは国際文字セットを扱う必要がある場合は、 mb_strtolower() を使用できます。

他の回答では strcasecmp() —その関数はマルチバイト文字を処理しないため、を使用することをお勧めします。 UTF-8文字列は偽物です。

100
asthasr

strcasecmp() は、文字列が同じ場合(大文字と小文字の違いを除く)に0を返すため、次を使用できます。

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

文字列がシングルバイトエンコーディングの場合、それは簡単です:

_if(strtolower($var1) === strtolower($var2))
_

文字列が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))
_

https://codepoints.nethttps://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を返しません!

しかし、ユニコードにはこれに対する解決策があります: Normalization ! 4つの異なる形式があります:NFC、NFD、NFKC、NFKD。文字列比較の場合、NFCとNFDは同等であり、NFKCとNFKDは同等です。NFKCはNFKDよりも短いので、 "ff"(_Latin Small Ligature ff, U+FB00_)は2つの通常の「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);
}
_

ご注意ください:

  • ノーマライザー には intl パッケージが必要です
  • 最初にそれらがちょうど等しいかどうかをチェックして、この関数を最適化する必要があります^^
  • nFKCはあなたの好みに合わせて多くのフォーマットの区別を削除するため、NFKCの代わりにNFCを使用したいかもしれません
  • この複雑さが本当に必要な場合、またはこの関数のより単純なバリアントを好む場合は、自分で決定する必要があります
14
Beat
if(strtolower($var1) == strtolower($var2)){
}
1
Shakti Singh

strcasecmp を使用します。

0
Oswald