2012-03-05 3 views
4

Quand je lance le code suivant, il ne pénètre pas dans la section « faire quelque chose »:Comparaison de deux chaînes Unicode avec perl

my $a ='µ╫P[┐╬♣3▀═<+·1╪מ└╖"ª'; 
my $b ='µ╫P[┐╬♣3▀═<+·1╪מ└╖"ª'; 

if ($a ne $b) { 
    # do something here  
} 

Y at-il une autre façon de comparer des chaînes Unicode avec perl?

+2

Pourquoi auriez-vous besoin d'un autre moyen? Y at-il quelque chose que vous recherchez que les comparaisons de chaînes intégrées ('eq',' ne', 'gt',' lt', 'ge', et' le') ne fournissent pas? –

+2

Si les chaînes sont égales (comme elles semblent l'être) alors je m'attendrais à ce que le bloc do do here ne soit pas entré. –

+6

Pour Perl de voir le fichier comme vous le faites, il doit être encodé en UTF-8 et vous devez utiliser 'utf8 use 'En supposant que vous avez fait cela, Perl fera un point de code par comparaison de code de la chaîne . Quels problèmes avez-vous? Avez-vous besoin de [normaliser] (http://search.cpan.org/perldoc?Unicode::Normalize) d'abord? – ikegami

Répondre

13

Si vous avez deux chaînes Unicode (à savoir la chaîne de points de code Unicode), alors vous avez sûrement enregistré votre fichier en UTF-8 et que vous aviez en fait

use utf8; # Tell Perl source code is UTF-8. 

my $a = 'µ╫P[┐╬♣3▀═<+·1╪מ└╖"ª'; 
my $b = 'µ╫P[┐╬♣3▀═<+·1╪מ└╖"ª'; 

if ($a eq $b) { 
    print("They're equal.\n"); 
} else { 
    print("They're not equal.\n"); 
} 

Et cela fonctionne parfaitement bien. eq et ne va comparer le code de chaînes point par point de code.

Certains graphèmes (par exemple "& eacute;") peuvent être construits de différentes manières, vous devrez donc d'abord représenter leur normalize.

use utf8; # Tell Perl source code is UTF-8. 

use charnames   qw(:full); # For \N{} 
use Unicode::Normalize qw(NFC); 

my $a = NFC("\N{LATIN SMALL LETTER E WITH ACUTE}"); 
my $b = NFC("e\N{COMBINING ACUTE ACCENT}"); 

if ($a eq $b) { 
    print("They're equal.\n"); 
} else { 
    print("They're not equal.\n"); 
} 

Enfin, Unicode considère certains caractères presque équivalent, et ils peuvent être considérés comme égaux en utilisant une forme différente de la normalisation.

use utf8; # Tell Perl source code is UTF-8. 

use charnames   qw(:full); # For \N{} 
use Unicode::Normalize qw(NFKC); 

my $a = NFKC("2"); 
my $b = NFKC("\N{SUPERSCRIPT TWO}"); 

if ($a eq $b) { 
    print("They're equal.\n"); 
} else { 
    print("They're not equal.\n"); 
} 
+8

'$ a' et' $ b' ne sont pas de bonnes variables pour lexicaliser, parce que 'sort {fc ($ a) cmp fc ($ b)} @ list' ne fonctionnera jamais. Aussi avec la normalisation, il y a les 33 singletons, qui ne sont pas une question d'ordre des marques. Enfin, il peut vouloir une sorte de comparaison mieux accomplie avec un objet 'Unicode :: Collate', mais nous ne le saurons pas sans clarification. Moi, je parie qu'il a un programme littéral qu'il compare avec quelque chose qu'il a lu dans un flux, et il n'a pas toutes ses ** capacités ** dans tous les bons endroits. Je ne sais pas, parce que l'extrait de code qu'il a donné ne raconte pas la vraie histoire. – tchrist

+1

@tchrist, Ces singletons ne font pas exception à ce que j'ai dit. Ces singletons (par exemple KELVIN SIGN) ont le même graphème (représentation visuelle) que les lettres (par exemple "LETTRE MAJUSCULE LATINE K") auxquelles ils sont considérés égaux. – ikegami

+0

Vous avez dit "peut être composé de plusieurs façons". Cela suggère quelque chose impliquant la combinaison de caractères et les singletons sont quelque chose d'autre. Ils ne sont pas un gros problème cependant. L'aspect «commande de marques» de la normalisation est généralement beaucoup plus important, sauf dans certains textes patrimoniaux contenant les anciens singletons. – tchrist