比较perl中的两个非ascii字符串

时间:2012-09-05 05:49:12

标签: perl

我无法比较两个非ascii字符串,尽管两个字符串在控制台上显示相同。以下是我的尝试。请告诉我这里缺少的代码,以便两个变量相等。

if($lineContent[7] ne $name) {
  /*Control coming to here*/
  print "###### Values MIS-MATCHED\n";
} else {
  print "###### Values MATCHED\n";
}

$lineContent[7]来自CSV文件

$name来自XML文件

当Putty的控制台处于默认的Characterset

CSV Val: ENB69-åºå°å±
XML Val: ENB69-åºå°å±

当Putty的控制台设置为UTF-8

CSV Val: ENB69-基地局
XML Val: ENB69-基地局

3 个答案:

答案 0 :(得分:3)

#!/usr/bin/perl

use warnings;
use strict;
use Encode;

binmode STDOUT, ":encoding(utf8)";
open F1, "<:utf8", "$ARGV[0]" or die "$!";
open F2, "<", "$ARGV[0]" or die "$!";

my $a1 = <F1>;
chomp $a1;
my $a2 = <F2>;
chomp $a2;

if ($a1 eq $a2) {
    print "$a1=$a2 is true\n";
} else {
    print "$a1=$a2 is false\n";
}

my $b = decode("utf-8", $a2);
if ($a1 eq $b) {
    print "$a1=$b is true\n";
} else { 
    print "$a1=$b is false\n";
}

我写了一个上面列出的测试程序。并用一行创建一个文本文件:基地局。 使用此文本文件运行程序时,可以获得false和true。 我不知道你的程序中有什么,但我想csv文件是作为纯文本读取的,没有任何解析器或编码/解码程序,而xml文件必须由某个库解析,因此内部编码机制是不同的对于两个字符串变量,包括编码表示法的一些前导字节。 简而言之,您可以尝试对两个字符串变量中的一个进行编码或解码,并查看它们是否匹配。

顺便说一句,这是我的第一个答案,希望对您有所帮助; - )

从您的转储结果来看,这是显而易见的。第一个变量存储9个字符,在其内部结构中以utf-8编码构成基地局。第二个变量在其内部结构中表示3个字符。它们具有相同的字节流,并且在字节流视图中相等,但在基于字符的比较中不相等。

使用decode / encode可以解决您的问题。

答案 1 :(得分:1)

如果你知道你正在比较unicode字符串,我个人会更加小心。 Unicode::Collate是工作的模块。

当然,您还应该阅读tchrist现在着名的关于在Perl中启用unicode的帖子https://stackoverflow.com/a/6163129/468327,但是utf8::all在开启正确的unicode支持方面做了令人钦佩的工作。请注意,版本5.14中的Perl核心添加了更好的unicode处理,所以我也需要这样。

最后,这是一个快速编写比较的脚本,当然你可以根据需要读取文件来填充变量:

#!/usr/bin/env perl

use v5.14;
use strict;
use warnings;

use utf8::all;
use Unicode::Collate;

my $collator = Unicode::Collate->new;

my $csv = "ENB69-基地局";
my $xml = "ENB69-基地局";

say $collator->eq($csv, $xml) ? "equal" : "unequal";

答案 2 :(得分:1)

您的意见:

"ENB13-\345\237\272\345\234\260\345\261\200"
"ENB13-\x{57fa}\x{5730}\x{5c40}"

如您所见,这些显然不一样。具体来说,第一个是另一个的UTF-8编码。始终解码输入。始终对输出进行编码。

use strict;
use warnings;

use utf8;                             # Source code is saved as UTF-8
use open ':std', ':encoding(UTF-8)';  # Terminal expects UTF-8

my $name = "ENB69-基地局";

while ($line = <STDIN>) {
   chomp;
   my @lineContent = split /\t/, $line;
   print($lineContent[7] eq $name ?1:0, "\n");  # 1
}