【发布时间】:2013-07-02 19:19:57
【问题描述】:
我有两个来自不同操作系统的 Json 文件。
这两个文件都以UTF-8 编码并包含UTF-8 编码filenames。
一个文件来自 OS X,文件名是 NFD 格式:(od -bc)
0000160 166 145 164 154 141 314 201 057 110 157 165 163 145 040 155 145
v e t l a ́ ** / H o u s e m e
第二个包含相同的文件名,但采用 NFC 形式:
000760 166 145 164 154 303 241 057 110 157 165 163 145 040 155 145 163
v e t l á ** / H o u s e m e s
据我所知,这称为“不同规范化”,有一个 CPAN 模块 Unicode::Normalize 用于处理它。
我正在用下一个读取这两个文件:
my $json1 = decode_json read_file($file1, {binmode => ':raw'}) or die "..." ;
my $json2 = decode_json read_file($file2, {binmode => ':raw'}) or die "..." ;
read_file 来自File::Slurp,decode_json 来自JSON::XS。
将 JSON 读入 perl 结构,文件名从一个 json 文件进入key 位置,从第二个文件进入values。当来自第一个哈希的哈希 key 与来自第二个哈希的 value 等效 时,我需要进行搜索,因此需要确保它们“二进制”相同。
尝试了下一个:
grep 'House' file1.json | perl -CSAD -MUnicode::Normalize -nlE 'print NFD($_)' | od -bc
和
grep 'House' file2.json | perl -CSAD -MUnicode::Normalize -nlE 'print NFD($_)' | od -bc
为我产生相同的输出。
现在问题:
- 如何简单地读取两个 json 文件以在
$hashrefs中获得相同的规范化?
或者在decode_json 之后需要在两个哈希上运行类似的东西?
while(my($k,$v) = each(%$json1)) {
$copy->{ NFD($k) } = NFD($v);
}
简而言之:
- 如何读取不同的 JSON 文件以在 perl
$href的“内部”获得相同的规范化?在每个keyvalue上显式执行NFD并创建另一个 NFD 规范化(大)哈希副本,是否可以实现更好的效果?
一些提示,建议 - 请...
因为我的英语很差,这里是一个问题的模拟
use 5.014;
use warnings;
use utf8;
use feature qw(unicode_strings);
use charnames qw(:full);
use open qw(:std :utf8);
use Encode qw(encode decode);
use Unicode::Normalize qw(NFD NFC);
use File::Slurp;
use Data::Dumper;
use JSON::XS;
#Creating two files what contains different "normalizations"
my($nfc, $nfd);;
$nfc->{ NFC('key') } = NFC('vál');
$nfd->{ NFD('vál') } = 'something';
#save as NFC - this comes from "FreeBSD"
my $jnfc = JSON::XS->new->encode($nfc);
open my $fd, ">:utf8", "nfc.json" or die("nfc");
print $fd $jnfc;
close $fd;
#save as NFD - this comes from "OS X"
my $jnfd = JSON::XS->new->encode($nfd);
open $fd, ">:utf8", "nfd.json" or die("nfd");
print $fd $jnfd;
close $fd;
#now read them
my $jc = decode_json read_file( "nfc.json", { binmode => ':raw' } ) or die "No file" ;
my $jd = decode_json read_file( "nfd.json", { binmode => ':raw' } ) or die "No file" ;
say $jd->{ $jc->{key} } // "NO FOUND"; #wanted to print "something"
my $jc2;
#is here a better way to DO THIS?
while(my($k,$v) = each(%$jc)) {
$jc2->{ NFD($k) } = NFD($v);
}
say $jd->{ $jc2->{key} } // "NO FOUND"; #OK
【问题讨论】: