Zeichenfolgenvergleich ohne Berücksichtigung der Groß- und Kleinschreibung

74

Ich möchte zwei Variablen vergleichen, um festzustellen, ob sie gleich sind, aber ich möchte, dass bei diesem Vergleich die Groß- und Kleinschreibung nicht berücksichtigt wird.

Dies würde beispielsweise zwischen Groß- und Kleinschreibung unterscheiden:

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

Aber ich möchte, dass die Groß- und Kleinschreibung nicht berücksichtigt wird. Wie würde ich das angehen?

Deniz Zoeteman
quelle

Antworten:

113

Das ist ziemlich einfach; Sie müssen nur strtolower()beide Variablen aufrufen .

Wenn Sie mit Unicode oder internationalen Zeichensätzen arbeiten müssen, können Sie verwenden mb_strtolower().

Bitte beachten Sie, dass andere Antworten die Verwendung dieser strcasecmp()Funktion vorschlagen. Diese Funktion verarbeitet keine Multibyte-Zeichen. Daher sind die Ergebnisse für alle UTF-8-Zeichenfolgen falsch.

asthasr
quelle
1
Im Allgemeinen glaube ich MySQL String - Vergleich ist Groß- und Kleinschreibung. Das heißt, 'A' = 'a'ist wahr. Eine Referenz: dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html
asthasr
4
Entschuldigung, ich bin kein Experte für MySQL. Vielleicht möchten Sie es als separate Frage veröffentlichen.
Asthasr
1
Beachten Sie, dass bei dieser Methode möglicherweise Zeichensatzprobleme auftreten (z. B. wenn Sie seltsame UTF-8-Zeichen verwenden). Verwenden Sie in diesem Fall mb_strtolower()stattdessen.
Balmipour
4
Leider ist dies nicht so einfach: In Unicode ist das Großbuchstaben der Kleinbuchstabenvariante möglicherweise nicht das gleiche wie das, mit dem Sie begonnen haben - und umgekehrt. Dh du musst mit mb_strtolower () UND mit mb_strttoupper () vergleichen.
Schlag
1
@robotik Ich kann keinen Kommentar bearbeiten, aber Sie können von meiner Antwort kopieren, es ist dort richtig;)
Beat
71

strcasecmp() Gibt 0 zurück, wenn die Zeichenfolgen identisch sind (abgesehen von Fallvariationen), sodass Sie Folgendes verwenden können:

if (strcasecmp($var1, $var2) == 0) {
}
Ramon
quelle
3
Denken Sie daran, auf == 0 zu testen. Dies ist nicht intuitiv, da es sehr verlockend ist, "if (strcasecmp ($ var1, $ var2)) {..." zu schreiben, aber in diesem Fall bedeutet 0 eher gleich als falsch-notequal, wie dies häufig der Fall ist.
Chirael
6
strcasecmp()behandelt keine Multibyte-Zeichen, daher kann es nicht mit Unicode umgehen.
Asthasr
15

Wenn sich Ihre Zeichenfolge in einer Einzelbyte-Codierung befindet, ist dies ganz einfach:

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

Wenn Ihre Zeichenfolge UTF-8 ist, müssen Sie die Komplexität von Unicode berücksichtigen: Kleinbuchstaben und Großbuchstaben sind keine bijektiven Funktionen. Wenn Sie also ein Kleinbuchstabenzeichen haben, transformieren Sie es in Großbuchstaben und transformieren Sie es Wenn Sie auf Kleinbuchstaben zurückgreifen, erhalten Sie möglicherweise nicht denselben Codepunkt (und dasselbe gilt, wenn Sie mit einem Großbuchstaben beginnen).

Z.B

  • "İ" ( Latin Capital Letter I with Dot Above, U+0130) ist ein Großbuchstabe mit "i" ( Latin Small Letter I, U+0069) als Kleinbuchstabenvariante - und die Großbuchstabenvariante von "i" ist "I" ( Latin Capital Letter I, U+0049).
  • "ı" ( Latin Small Letter Dotless I, U+0131) ist ein Kleinbuchstaben mit "I" ( Latin Capital Letter I, U+0049) als Großbuchstabenvariante - und die Kleinbuchstabenvariante von "I" ist "i" ( Latin Small Letter I, U+0069)

So mb_strtolower('ı') === mb_strtolower('i')gibt false zurück, auch wenn sie die gleichen Großbuchstaben haben. Wenn Sie wirklich eine Vergleichsfunktion für Zeichenfolgen ohne Berücksichtigung der Groß- und Kleinschreibung wünschen, müssen Sie diese mit der Groß- und Kleinschreibung vergleichen:

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

Ich habe eine Abfrage für die Unicode-Datenbank von https://codepoints.net ( https://dumps.codepoints.net ) ausgeführt und 180 Codepunkte gefunden, für die ich ein anderes Zeichen gefunden habe, wenn ich Kleinbuchstaben verwendet habe Kleinbuchstaben und 8 Codepunkte, für die ich ein anderes Zeichen gefunden habe, als ich die Großbuchstaben eines Großbuchstabens genommen habe

Aber es wird schlimmer : Der gleiche Graphemcluster, den der Benutzer sieht, kann mehrere Arten der Codierung haben: "ä" kann als Latin Small Letter a with Diaeresis (U+00E4)oder als Latin Small Letter A (U+0061)und dargestellt werden Combining Diaeresis (U+0308)- und wenn Sie sie auf Byte-Ebene vergleichen, wird dies nicht true zurückgeben!

Dafür gibt es in Unicode eine Lösung: Normalisierung ! Es gibt vier verschiedene Formen: NFC, NFD, NFKC, NFKD. Für den Zeichenfolgenvergleich sind NFC und NFD äquivalent und NFKC und NFKD sind äquivalent. Ich würde NFKC nehmen, da es kürzer als NFKD ist und "ff" ( Latin Small Ligature ff, U+FB00) in zwei normale "f" umgewandelt wird (aber 2⁵ wird auch auf 25 erweitert ...).

Die resultierende Funktion wird:

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

Bitte beachten Sie:

  • Sie benötigen das intl- Paket für den Normalizer
  • Sie sollten diese Funktion optimieren, indem Sie zuerst prüfen, ob sie gerade gleich sind ^^
  • Möglicherweise möchten Sie NFC anstelle von NFKC verwenden, da NFKC zu viele Formatierungsunterschiede für Ihren Geschmack entfernt
  • Sie müssen selbst entscheiden, ob Sie diese Komplexität wirklich benötigen oder ob Sie eine einfachere Variante dieser Funktion bevorzugen
Schlagen
quelle
1
if(strtolower($var1) == strtolower($var2)){
}
Shakti Singh
quelle
Obwohl ich diese Technik verstehe und sie ziemlich einfach ist, ist dies keine großzügige oder erklärte Antwort. Wenn neue Forscher alte Nur-Code-Antworten sehen, werden sie anfangen zu denken, dass dies eine absolut akzeptable Antwort auf Stackoverflow ist. Bitte modellieren Sie ein besseres Posting-Verhalten mit der Absicht, zu informieren, anstatt eine Lösung zu entleeren und sich zu verstecken.
Mickmackusa
0

Warum nicht:

if(strtolower($var1) == strtolower($var2)){
}
jpea
quelle
0

Verwenden Sie strcasecmp .

Oswald
quelle
Wie bei anderen Antworten erwähnt, ist dies für Unicode fehlerhaft.
TextGeek