Wie vergleiche ich zwei Zeichenfolgen in Perl?

178

Wie vergleiche ich zwei Zeichenfolgen in Perl?

Ich lerne Perl, ich hatte diese grundlegende Frage hier auf StackOverflow nachgeschlagen und fand keine gute Antwort, also dachte ich, ich würde fragen.

PJT
quelle
3
Sie sollten zuerst die ausgezeichnete Dokumentation konsultieren, die mit Perl geliefert wird.
Sinan Ünür
5
Vielleicht möchten Sie sich ein Buch wie Learning Perl (das ich mitautorisiert habe) ansehen. Es gab keine guten Antworten auf diese Frage, weil sie sehr einfach ist. Ein Tutorial hilft Ihnen dabei, die Grundlagen schnell zu erlernen.
Brian D Foy

Antworten:

184

Siehe Perldoc Perlop . Verwenden Sie lt, gt, eq, ne, und cmpals geeignet für String - Vergleiche:

Binary eqgibt true zurück, wenn das linke Argument dem rechten Argument entspricht.

Binary negibt true zurück, wenn das linke Argument nicht dem rechten Argument entspricht.

Binary cmpgibt -1, 0 oder 1 zurück, je nachdem, ob das linke Argument in der Zeichenfolge kleiner, gleich oder größer als das rechte Argument ist.

Binary ~~führt ein Smartmatch zwischen seinen Argumenten durch. ...

lt, le, ge, gtUnd cmpdie Sortierung (sortiert) , um von der aktuellen Locale angegeben verwenden , wenn ein Legacy - Anwendung locale (aber nicht use locale ':not_characters') in Kraft ist. Siehe Perllocale . Mischen Sie diese nicht mit Unicode, sondern nur mit älteren Binärcodierungen. Die Standardmodule Unicode :: Collate und Unicode :: Collate :: Locale bieten viel leistungsfähigere Lösungen für Sortierprobleme .

Sinan Ünür
quelle
9
Nur noch eine, ne für ungleich.
PJT
4
Vielleicht möchten Sie erwähnen, dass $ str1 = ~ "$ str2" (nicht / $ str2 /) prüft, ob $ str2 eine Teilzeichenfolge von $ str1 ist.
Daniel C. Sobral
@Daniel verwendet, um indexzu sehen, ob eine Zeichenfolge eine Teilzeichenfolge einer anderen ist.
Sinan Ünür
3
@ Daniel: Es gibt keinen großen praktischen Unterschied zwischen = ~ "$ str2" und = ~ / $ str2 / (oder nur = ~ $ str2); index ist das richtige Werkzeug, aber wenn Sie aus irgendeinem Grund einen regulären Ausdruck verwenden müssen, tun Sie = ~ / \ Q $ str2 \ E /.
ysth
1
@IliaRostovtsev !=und nesind nicht gleich, weil !=und neals unterschiedlich definiert sind. Wie schwer ist das?! !=Konvertiert als numerischer Vergleichsoperator beide Operanden in Zahlen perl -E 'say "equal" if not "a" != "b"'.
Sinan Ünür
137
  • cmp Vergleichen Sie

    'a' cmp 'b' # -1
    'b' cmp 'a' #  1
    'a' cmp 'a' #  0
  • eq Gleich

    'a' eq  'b' #  0
    'b' eq  'a' #  0
    'a' eq  'a' #  1
  • ne Nicht gleichzusetzen mit

    'a' ne  'b' #  1
    'b' ne  'a' #  1
    'a' ne  'a' #  0
  • lt Weniger als

    'a' lt  'b' #  1
    'b' lt  'a' #  0
    'a' lt  'a' #  0
  • le Gleich oder kleiner als

    'a' le  'b' #  1
    'b' le  'a' #  0
    'a' le  'a' #  1
  • gt Größer als

    'a' gt  'b' #  0
    'b' gt  'a' #  1
    'a' gt  'a' #  0
  • ge Größer als oder gleich wie

    'a' ge  'b' #  0
    'b' ge  'a' #  1
    'a' ge  'a' #  1

Siehe perldoc perlopfür weitere Informationen.

(Ich vereinfache dies ein wenig, gebe aber cmpeinen Wert zurück, der sowohl eine leere Zeichenfolge als auch einen numerischen Nullwert anstelle von 0und einen Wert ist, der sowohl die Zeichenfolge '1'als auch den numerischen Wert ist 1. Dies sind die gleichen Werte, die Sie verwenden werden Immer von booleschen Operatoren in Perl erhalten. Sie sollten wirklich nur die Rückgabewerte für boolesche oder numerische Operationen verwenden. In diesem Fall spielt der Unterschied keine Rolle.)

Brad Gilbert
quelle
8
Ich mag diese Antwort mehr. Kurze einfache Beispiele sind für Neulinge in der Regel hilfreicher als nur banale mehrseitige Dokumentreferenzen.
Zon
@Zon der Ausnahme , dass die Rückgabewerte für eq, gt, ltetc. sind nicht richtig ... Sie kehren wahr oder falsch. Nur cmpgibt bestimmte numerische Werte.
Sinan Ünür
Perl 6 verwendet dieselben Operatoren, außer dass sie legstattdessen cmpfür generische Vergleiche verwendet werden.
Brad Gilbert
17

Zusätzlich zu Sinan Ünürs umfassender Liste von String-Vergleichsoperatoren fügt Perl 5.10 den Smart Match-Operator hinzu.

Der Smart Match-Operator vergleicht zwei Elemente anhand ihres Typs. In der folgenden Tabelle finden Sie das Verhalten von 5.10 (ich glaube, dieses Verhalten ändert sich in 5.10.1 geringfügig):

perldoc perlsyn"Smart Matching im Detail" :

Das Verhalten eines Smart Matchs hängt davon ab, um welche Art von Argumenten es sich handelt. Es ist immer kommutativ, dh es $a ~~ $bverhält sich genauso wie $b ~~ $a. Das Verhalten wird durch die folgende Tabelle bestimmt: Die erste Zeile, die in beliebiger Reihenfolge angewendet wird, bestimmt das Übereinstimmungsverhalten.

  $ a $ b Art der Übereinstimmung Impliziter Übereinstimmungscode
  ====== ===== ======================
  (Überladung übertrumpft alles)

  Code [+] Code [+] referentielle Gleichheit $ a == $ b   
  Beliebige skalare Code [+] -Unterwahrheit $ b -> ($ a)   

  Hash Hash Hash-Schlüssel identisch [Sortierschlüssel% $ a] ~~ [Sortierschlüssel% $ b]
  Hash Array Hash Slice Existenz grep {existiert $ a -> {$ _}} @ $ b
  Hash Regex Hash-Schlüssel grep grep / $ b /, Schlüssel% $ a
  Hash Es existiert ein Hash-Eintrag $ a -> {$ b}

  Array Array-Arrays sind identisch [*]
  Array Regex-Array grep grep / $ b /, @ $ a
  Array Num Array enthält die Nummer grep $ _ == $ b, @ $ a 
  Array Jedes Array enthält den String grep $ _ eq $ b, @ $ a 

  Alle undef undefined! Defined $ a
  Jedes Regex-Muster entspricht $ a = ~ / $ b / 
  Code () Code () Ergebnisse sind gleich $ a -> () eq $ b -> ()
  Jeder Code () einfache Abschlusswahrheit $ b -> () # ignoriert $ a
  Num numish [!] Numerische Gleichheit $ a == $ b   
  Beliebige Str-String-Gleichheit $ a eq $ b   
  Beliebige numerische Gleichheit $ a == $ b   

  Beliebig Beliebige Zeichenfolgengleichheit $ a eq $ b   

+ - Dies muss eine Code-Referenz sein, deren Prototyp (falls vorhanden) nicht "" ist.
(Subs mit einem "" Prototyp werden durch den Eintrag "Code ()" weiter unten behandelt) 
* - Das heißt, jedes Element entspricht dem Element desselben Index im anderen
Array. Wenn eine Zirkelreferenz gefunden wird, greifen wir auf die Referenz zurück
Gleichberechtigung.   
! - entweder eine reelle Zahl oder eine Zeichenfolge, die wie eine Zahl aussieht

Der "Übereinstimmungscode" repräsentiert natürlich nicht den tatsächlichen Übereinstimmungscode: Er dient nur dazu, die beabsichtigte Bedeutung zu erklären. Im Gegensatz zu grep wird der Smart Match-Operator kurzschließen, wann immer er kann.

Benutzerdefinierter Abgleich durch Überladen Sie können die Art und Weise ändern, in der ein Objekt abgeglichen wird, indem Sie den ~~Operator überladen . Dies übertrifft die übliche Smart-Match-Semantik. Siehe overload.

Chas. Owens
quelle
Es ändert sich nicht leicht: Es ändert sich radikal. Smart Matching für alles, was nicht einfach ist, ist ernsthaft kaputt.
Brian D Foy
1
Der Link sollte sich wahrscheinlich ändern, da sich die Dokumente in der Zwischenzeit geändert haben. 5.14.2 aktuell
Brad Gilbert
10
print "Matched!\n" if ($str1 eq $str2)

Perl verfügt über separate Zeichenfolgenvergleichs- und numerische Vergleichsoperatoren, um die lose Eingabe in der Sprache zu erleichtern. Sie sollten Perlop für alle verschiedenen Operatoren lesen .

Matthew Scharley
quelle
8

Der offensichtliche Untertext dieser Frage lautet:

Warum können Sie nicht einfach ==überprüfen, ob zwei Zeichenfolgen gleich sind?

Perl hat keine unterschiedlichen Datentypen für Text oder Zahlen. Sie werden beide durch den Typ "Skalar" dargestellt . Anders ausgedrückt, Zeichenfolgen sind Zahlen, wenn Sie sie als solche verwenden .

if ( 4 == "4" ) { print "true"; } else { print "false"; }
true

if ( "4" == "4.0" ) { print "true"; } else { print "false"; }
true

print "3"+4
7

Da Text und Zahlen nicht durch die Sprache unterschieden werden, können wir den ==Operator nicht einfach überladen , um in beiden Fällen das Richtige zu tun. Daher bietet Perl die Möglichkeit eq, Werte als Text zu vergleichen:

if ( "4" eq "4.0" ) { print "true"; } else { print "false"; }
false

if ( "4.0" eq "4.0" ) { print "true"; } else { print "false"; }
true

Zusamenfassend:

  • Perl hat keinen Datentyp ausschließlich für Textzeichenfolgen
  • Verwenden Sie ==oder !=, um zwei Operanden als Zahlen zu vergleichen
  • Verwenden Sie eqoder ne, um zwei Operanden als Text zu vergleichen

Es gibt viele andere Funktionen und Operatoren, mit denen Skalarwerte verglichen werden können. Die Unterscheidung zwischen diesen beiden Formen ist jedoch ein wichtiger erster Schritt.

kein Balken
quelle
Java hat das gleiche Problem, jedoch aus einem anderen Grund (und mit unterschiedlichen Auswirkungen).
Nobar
1

Und wenn Sie die Unterschiede zwischen den beiden Zeichenfolgen extrahieren möchten, können Sie String :: Diff verwenden .

Helen Craigman
quelle
Wenn Sie auf die Perl-Dokumentation verlinken möchten, wird normalerweise empfohlen, Permalinks zu verwenden, die immer auf die neueste Version des Moduls verweisen. search.cpan.org/perldoc/String::Diff search.cpan.org/perldoc?String::Diff p3rl.org/String::Diff metacpan.org/module/String::Diff metacpan.org/pod/String: : Diff Done
Brad Gilbert