Jak porównać dwa ciągi w Perlu?

178

Jak porównać dwa ciągi w Perlu?

Uczę się Perla, miałem to podstawowe pytanie, sprawdziłem je tutaj w StackOverflow i nie znalazłem dobrej odpowiedzi, więc pomyślałem, że zapytam.

PJT
źródło
3
Najpierw należy zapoznać się z doskonałą dokumentacją dołączoną do Perla.
Sinan Ünür
5
Możesz zajrzeć do książki, takiej jak Learning Perl (której jestem współautorem). Nie było dobrych odpowiedzi na to pytanie, ponieważ jest bardzo podstawowe. Samouczek pomoże Ci szybko opanować podstawy.
brian d foy

Odpowiedzi:

184

Zobacz perldoc perlop . Zastosowanie lt, gt, eq, ne, i cmpodpowiednio dla porównań łańcuchowych:

eqFunkcja binarna zwraca prawdę, jeśli lewy argument jest ciągiem równy prawemu.

Dwójkowy neFunkcja zwraca prawdę, jeśli lewy argument jest ciągiem różnym od prawego.

Binarny cmpzwraca -1, 0 lub 1 w zależności od tego, czy lewy argument jest ciągiem mniejszy niż, równy lub większy niż prawy argument.

Binary ~~wykonuje smartmatch między swoimi argumentami. ...

lt, le, ge, gtI cmpużyć sortowania (sortowanie) Order określonej przez bieżące locale jeśli locale użycie starszego typu (nie use locale ':not_characters') jest w istocie. Zobacz perllocale . Nie mieszaj ich z Unicode, tylko ze starszymi kodowaniami binarnymi. Standardowe moduły Unicode :: Collate i Unicode :: Collate :: Locale oferują znacznie bardziej zaawansowane rozwiązania problemów z sortowaniem.

Sinan Ünür
źródło
9
Jeszcze tylko jeden, nie równy.
PJT,
4
Możesz chcieć wspomnieć, że $ str1 = ~ "$ str2" (nie / $ str2 /) sprawdzi, czy $ str2 jest podłańcuchem $ str1.
Daniel C. Sobral
@Daniel użyj, indexaby sprawdzić, czy ciąg jest podłańcuchem innego.
Sinan Ünür
3
@Daniel: nie ma zbyt dużej praktycznej różnicy między = ~ "$ str2" a = ~ / $ str2 / (lub po prostu = ~ $ str2); index to właściwe narzędzie, ale jeśli z jakiegoś powodu potrzebujesz użyć wyrażenia regularnego, wykonaj = ~ / \ Q $ str2 \ E /.
ysth
1
@IliaRostovtsev !=i nenie są takie same, ponieważ !=i nesą zdefiniowane jako różne. Jak trudne to jest ?! Będąc liczbowym operatorem porównania, !=konwertuje oba operandy na liczby perl -E 'say "equal" if not "a" != "b"'.
Sinan Ünür
137
  • cmp Porównać

    'a' cmp 'b' # -1
    'b' cmp 'a' #  1
    'a' cmp 'a' #  0
  • eq Równy

    'a' eq  'b' #  0
    'b' eq  'a' #  0
    'a' eq  'a' #  1
  • ne Nie równe

    'a' ne  'b' #  1
    'b' ne  'a' #  1
    'a' ne  'a' #  0
  • lt Mniej niż

    'a' lt  'b' #  1
    'b' lt  'a' #  0
    'a' lt  'a' #  0
  • le Mniejszy lub równy

    'a' le  'b' #  1
    'b' le  'a' #  0
    'a' le  'a' #  1
  • gt Lepszy niż

    'a' gt  'b' #  0
    'b' gt  'a' #  1
    'a' gt  'a' #  0
  • ge Większe bądź równe

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

Zobacz, perldoc perlopaby uzyskać więcej informacji.

(Upraszczam to trochę, ponieważ wszystkie cmpzwracają wartość, która jest zarówno pustym ciągiem, jak i wartością numeryczną zero zamiast 0, oraz wartością, która jest zarówno ciągiem, jak '1'i wartością liczbową 1. Są to te same wartości, które będziesz zawsze otrzymuj z operatorów logicznych w Perlu. Zwracane wartości powinny być używane tylko dla operacji logicznych lub numerycznych, w takim przypadku różnica nie ma znaczenia).

Brad Gilbert
źródło
8
Bardziej podoba mi się ta odpowiedź. Krótkie, proste przykłady są zwykle bardziej pomocne dla początkujących, niż tylko banalne odniesienia do wielostronicowych dokumentów.
Zon,
@Zon wyjątkiem, że wartości zwrotu dla eq, gt, ltetc nie są poprawne ... Wracają prawdziwe lub fałszywe. cmpZwraca tylko określone wartości liczbowe.
Sinan Ünür
Perl 6 używa tych samych operatorów, z wyjątkiem tego, że legzamiast cmpnich jest używany do porównań ogólnych.
Brad Gilbert,
17

Oprócz obszernej listy operatorów porównania ciągów przez Sinana Ünür, Perl 5.10 dodaje operator inteligentnego dopasowania.

Operator inteligentnego dopasowania porównuje dwa elementy na podstawie ich typu. Zobacz poniższy wykres dla zachowania 5.10 (uważam, że to zachowanie zmienia się nieznacznie w 5.10.1):

perldoc perlsyn„Inteligentne dopasowanie szczegółów” :

Zachowanie inteligentnego dopasowania zależy od typu rzeczy, które są jego argumentami. Jest zawsze przemienny, tj. $a ~~ $bZachowuje się tak samo jak $b ~~ $a. Zachowanie określa następująca tabela: pierwszy wiersz, który ma zastosowanie, w dowolnej kolejności, określa zachowanie dopasowania.

  $ a $ b Rodzaj dopasowania Domniemany kod dopasowania
  ====== ===== ===================== =============
  (przeciążenie przebija wszystko)

  Kod [+] Kod [+] równość referencyjna $ a == $ b   
  Dowolny kod [+] skalarna prawda podrzędna $ b -> ($ a)   

  Hash Hash Hash klucze identyczne [klucze sortowania% $ a] ~~ [klucze sortowania% $ b]
  Hash Array istnienie wycinka skrótu grep {istnieje $ a -> {$ _}} @ $ b
  Hash Regex hash key grep grep / $ b /, klucze% $ a
  Hash Istnieje każdy wpis z hashem $ a -> {$ b}

  Tablice Tablice Tablice są identyczne [*]
  Tablica Regex tablica grep grep / $ b /, @ $ a
  Tablica Num Tablica zawiera liczbę grep $ _ == $ b, @ $ a 
  Tablica Dowolna tablica zawiera ciąg grep $ _ eq $ b, @ $ a 

  Dowolne undef undefined! Define $ a
  Dowolny wzorzec Regex pasuje do $ a = ~ / $ b / 
  Code () Wyniki Code () są równe $ a -> () eq $ b -> ()
  Dowolne proste zamknięcie Code () $ b -> () # ignorujące $ a
  Num numish [!] Równość numeryczna $ a == $ b   
  Dowolna równość łańcucha Str $ a eq $ b   
  Dowolna równość liczbowa Num $ a == $ b   

  Dowolna Dowolna równość łańcuchowa $ a eq $ b   

+ - musi to być odwołanie do kodu, którego prototyp (jeśli istnieje) nie jest ""
(subskrypcje z prototypem „” są obsługiwane przez pozycję „Kod ()” na dole) 
* - czyli każdy element pasuje do elementu o tym samym indeksie w drugim
szyk. Jeśli zostanie znalezione odwołanie cykliczne, wracamy do referencji
równość.   
! - liczba rzeczywista lub ciąg, który wygląda jak liczba

Oczywiście „pasujący kod” nie reprezentuje prawdziwego pasującego kodu: służy tylko do wyjaśnienia zamierzonego znaczenia. W przeciwieństwie do grepa, inteligentny operator dopasuje zwarcie, kiedy tylko będzie to możliwe.

Dopasowywanie niestandardowe przez przeciążanie Możesz zmienić sposób dopasowywania obiektu przez przeciążenie ~~operatora. To przebija zwykłą semantykę inteligentnego dopasowania. Zobacz overload.

Chas. Owens
źródło
Nie zmienia się nieznacznie: zmienia się radykalnie. Inteligentne dopasowywanie wszystkiego, co niełatwe, jest poważnie zepsute.
brian d foy
1
Link powinien prawdopodobnie ulec zmianie, ponieważ dokumenty zmieniły się w międzyczasie. 5.14.2 obecnie
Brad Gilbert
10
print "Matched!\n" if ($str1 eq $str2)

Perl ma oddzielne operatory porównania ciągów i liczb, które pomagają w luźnym pisaniu w języku. Powinieneś przeczytać perlop dla wszystkich różnych operatorów.

Matthew Scharley
źródło
8

Oczywistym podtekstem tego pytania jest:

dlaczego nie możesz po prostu użyć ==do sprawdzenia, czy dwa ciągi są takie same?

Perl nie ma odrębnych typów danych dla tekstu i liczb. Oba są reprezentowane przez typ „skalarny” . Innymi słowy, łańcuchy liczbami, jeśli używasz ich jako takich .

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

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

print "3"+4
7

Ponieważ tekst i liczby nie są rozróżniane na podstawie języka, nie możemy po prostu przeciążać ==operatora, aby zrobił właściwą rzecz w obu przypadkach. Dlatego Perl umożliwia eqporównywanie wartości jako tekstu:

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

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

W skrócie:

  • Perl nie ma typu danych wyłącznie dla ciągów tekstowych
  • użyj ==lub !=, aby porównać dwa operandy jako liczby
  • użyj eqlub ne, aby porównać dwa operandy jako tekst

Istnieje wiele innych funkcji i operatorów, których można użyć do porównania wartości skalarnych, ale znajomość różnicy między tymi dwoma formami jest ważnym pierwszym krokiem.

Brent Bradburn
źródło
Java ma ten sam problem, ale z innego powodu (i z innymi konsekwencjami).
Brent Bradburn
1

A jeśli chcesz wyodrębnić różnice między dwoma ciągami, możesz użyć String :: Diff .

Helen Craigman
źródło
Jeśli masz zamiar łączyć się z dokumentacją Perla, zwykle zaleca się użycie linków bezpośrednich, które zawsze będą prowadzić do najnowszej wersji modułu. 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,