Comment comparer deux chaînes en Perl?

178

Comment comparer deux chaînes en Perl?

J'apprends Perl, j'avais cette question de base recherchée ici sur StackOverflow et je n'ai trouvé aucune bonne réponse, alors j'ai pensé que je demanderais.

PJT
la source
3
Vous devriez d'abord consulter l'excellente documentation fournie avec Perl.
Sinan Ünür
5
Vous voudrez peut-être consulter un livre tel que Learning Perl (que j'ai co-écrit). Il n'y avait pas de bonnes réponses à cette question car elle est très basique. Un tutoriel vous aidera à comprendre rapidement les bases.
brian d foy

Réponses:

184

Voir perldoc perlop . Utilisez lt, gt, eq, neet cmple cas échéant pour les comparaisons de chaînes:

Binary eqrenvoie true si l'argument de gauche est égal dans le sens de la chaîne à l'argument de droite.

Binaire ne renvoie true si l'argument de gauche n'est pas égal à l'argument de droite dans le sens d'une chaîne.

Binary cmprenvoie -1, 0 ou 1 selon que l'argument de gauche est inférieur, égal ou supérieur à l'argument de droite dans le sens de la chaîne.

Binary ~~effectue un smartmatch entre ses arguments. ...

lt, le, ge, gtEt cmputiliser le tri (collation) ordre spécifié par les paramètres régionaux en cours si un lieu d'utilisation de l' héritage (mais pas use locale ':not_characters') est en vigueur. Voir perllocale . Ne les mélangez pas avec Unicode, uniquement avec des encodages binaires hérités. Les modules standard Unicode :: Collate et Unicode :: Collate :: Locale offrent des solutions beaucoup plus puissantes aux problèmes de classement.

Sinan Ünür
la source
9
Juste un de plus, ne pour pas égal.
PJT
4
Vous voudrez peut-être mentionner que $ str1 = ~ "$ str2" (pas / $ str2 /) vérifiera si $ str2 est une sous-chaîne de $ str1.
Daniel C.Sobral
@Daniel utilise indexpour voir si une chaîne est une sous-chaîne d'une autre.
Sinan Ünür
3
@Daniel: il n'y a pas beaucoup de différence pratique entre = ~ "$ str2" et = ~ / $ str2 / (ou juste = ~ $ str2 d'ailleurs); index est le bon outil, mais si vous avez besoin d'utiliser une expression régulière pour une raison quelconque, faites = ~ / \ Q $ str2 \ E /.
ysth
1
@IliaRostovtsev !=et nene sont pas les mêmes, car !=et nesont définis comme étant différents. Est-ce difficile?! Étant un opérateur de comparaison numérique, !=convertit ses deux opérandes en nombres perl -E 'say "equal" if not "a" != "b"'.
Sinan Ünür
137
  • cmp Comparer

    'a' cmp 'b' # -1
    'b' cmp 'a' #  1
    'a' cmp 'a' #  0
  • eq Égal à

    'a' eq  'b' #  0
    'b' eq  'a' #  0
    'a' eq  'a' #  1
  • ne Pas égal à

    'a' ne  'b' #  1
    'b' ne  'a' #  1
    'a' ne  'a' #  0
  • lt Moins que

    'a' lt  'b' #  1
    'b' lt  'a' #  0
    'a' lt  'a' #  0
  • le Inférieur ou égal à

    'a' le  'b' #  1
    'b' le  'a' #  0
    'a' le  'a' #  1
  • gt Plus grand que

    'a' gt  'b' #  0
    'b' gt  'a' #  1
    'a' gt  'a' #  0
  • ge Plus grand ou égal à

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

Voir perldoc perloppour plus d'informations.

(Je simplifie un peu cela car tout sauf cmpretourne une valeur qui est à la fois une chaîne vide et une valeur numérique zéro au lieu de 0, et une valeur qui est à la fois la chaîne '1'et la valeur numérique 1. Ce sont les mêmes valeurs que vous toujours obtenir des opérateurs booléens en Perl. Vous ne devriez vraiment utiliser les valeurs de retour que pour les opérations booléennes ou numériques, auquel cas la différence n'a pas vraiment d'importance.)

Brad Gilbert
la source
8
J'aime plus cette réponse. De courts exemples simples sont généralement plus utiles pour les débutants, que la simple référence à des documents multipages banals.
Zon
@Zon sauf que les valeurs de retour pour eq, gt, ltetc ne sont pas correctes ... Ils renvoient vrai ou faux. Renvoie uniquement cmpdes valeurs numériques spécifiques.
Sinan Ünür
Perl 6 utilise les mêmes opérateurs sauf qu'il utilise à la legplace cmpce qui est utilisé pour les comparaisons génériques à la place.
Brad Gilbert
17

En plus de la liste complète des opérateurs de comparaison de chaînes de Sinan Ünür, Perl 5.10 ajoute l'opérateur de correspondance intelligente.

L'opérateur de correspondance intelligente compare deux éléments en fonction de leur type. Voir le tableau ci-dessous pour le comportement 5.10 (je pense que ce comportement change légèrement dans 5.10.1):

perldoc perlsyn"Correspondance intelligente en détail" :

Le comportement d'une correspondance intelligente dépend du type d'objet de ses arguments. Il est toujours commutatif, c'est-à-dire qu'il $a ~~ $bse comporte de la même manière que $b ~~ $a. Le comportement est déterminé par le tableau suivant: la première ligne qui s'applique, dans l'un ou l'autre ordre, détermine le comportement de correspondance.

  $ a $ b Type de correspondance Code de correspondance implicite
  ====== ===== ===================== =============
  (la surcharge l'emporte sur tout)

  Code [+] Code [+] égalité référentielle $ a == $ b   
  Tout code [+] sous-vérité scalaire $ b -> ($ a)   

  Hash Hash Clés de hachage identiques [clés de tri% $ a] ~~ [clés de tri% $ b]
  Hash Array existence d'une tranche de hachage grep {existe $ a -> {$ _}} @ $ b
  Clé de hachage Hash Regex grep grep / $ b /, clés% $ a
  Hash Toute existence d'entrée de hachage existe $ a -> {$ b}

  Les tableaux Array Array sont identiques [*]
  Tableau Regex tableau grep grep / $ b /, @ $ a
  Le tableau Array Num contient le nombre grep $ _ == $ b, @ $ a 
  Tableau Tout tableau contient la chaîne grep $ _ eq $ b, @ $ a 

  Tout undef undefined! Defined $ a
  Tout modèle Regex correspond à $ a = ~ / $ b / 
  Code () Les résultats de Code () sont égaux $ a -> () eq $ b -> ()
  Toute vérité de fermeture simple Code () $ b -> () # ignorant $ a
  Num numish [!] Égalité numérique $ a == $ b   
  Toute égalité de chaîne Str $ a eq $ b   
  Toute égalité numérique numérique $ a == $ b   

  Any Toute égalité de chaîne $ a eq $ b   

+ - il doit s'agir d'une référence de code dont le prototype (s'il est présent) n'est pas ""
(les sous-marins avec un prototype "" sont traités par l'entrée 'Code ()' plus bas) 
* - c'est-à-dire que chaque élément correspond à l'élément du même index dans l'autre
tableau. Si une référence circulaire est trouvée, on retombe au référentiel
égalité.   
! - soit un nombre réel, soit une chaîne qui ressemble à un nombre

Le "code correspondant" ne représente pas le vrai code correspondant, bien sûr: il est juste là pour expliquer la signification voulue. Contrairement à grep, l'opérateur de correspondance intelligente court-circuitera chaque fois qu'il le peut.

Correspondance personnalisée via la surcharge Vous pouvez modifier la manière dont un objet est mis en correspondance en surchargeant l' ~~opérateur. Cela l'emporte sur la sémantique habituelle des correspondances intelligentes. Voir overload.

Chas. Owens
la source
Ça ne change pas un peu: ça change radicalement. L'appariement intelligent pour tout ce qui n'est pas simple est sérieusement cassé.
brian d foy
1
Le lien devrait probly changer car les docs ont changé entre-temps. 5.14.2 actuel
Brad Gilbert
10
print "Matched!\n" if ($str1 eq $str2)

Perl a des opérateurs de comparaison de chaînes et de comparaison numériques séparés pour faciliter la saisie lâche dans le langage. Vous devriez lire perlop pour tous les différents opérateurs.

Matthew Scharley
la source
8

Le sous-texte évident de cette question est:

pourquoi ne pouvez-vous pas simplement utiliser ==pour vérifier si deux chaînes sont identiques?

Perl n'a pas de types de données distincts pour le texte et les nombres. Ils sont tous deux représentés par le type "scalaire" . En d'autres termes, les chaînes sont des nombres si vous les utilisez comme tels .

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

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

print "3"+4
7

Puisque le texte et les nombres ne sont pas différenciés par la langue, nous ne pouvons pas simplement surcharger l' ==opérateur pour qu'il fasse ce qu'il faut dans les deux cas. Par conséquent, Perl propose eqde comparer les valeurs sous forme de texte:

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

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

En bref:

  • Perl n'a pas de type de données exclusivement pour les chaînes de texte
  • utilisez ==ou !=, pour comparer deux opérandes sous forme de nombres
  • utiliser eqou ne, pour comparer deux opérandes sous forme de texte

Il existe de nombreuses autres fonctions et opérateurs pouvant être utilisés pour comparer des valeurs scalaires, mais connaître la distinction entre ces deux formes est une première étape importante.

Brent Bradburn
la source
Java a le même problème, mais pour une raison différente (et avec des implications différentes).
Brent Bradburn
1

Et si vous souhaitez extraire les différences entre les deux chaînes, vous pouvez utiliser String :: Diff .

Helen Craigman
la source
Si vous voulez créer un lien vers la documentation Perl, il est généralement recommandé d'utiliser des Permaliens qui seront toujours liés à la dernière version du module. 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