我有两个来自不同操作系统的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
Run Code Online (Sandbox Code Playgroud)
第二个包含相同的文件名但以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
Run Code Online (Sandbox Code Playgroud)
据我所知,这被称为"不同的规范化",并且有一个Unicode::Normalize用于处理它的CPAN模块.
我正在阅读下一个文件:
my $json1 = decode_json read_file($file1, {binmode => ':raw'}) or die "..." ;
my $json2 = decode_json read_file($file2, {binmode => ':raw'}) or die "..." ;
Run Code Online (Sandbox Code Playgroud)
read_file来自from 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
Run Code Online (Sandbox Code Playgroud)
和
grep 'House' file2.json | perl -CSAD -MUnicode::Normalize -nlE 'print NFD($_)' | od -bc
Run Code Online (Sandbox Code Playgroud)
为我生产相同的输出.
现在的问题是:
$hashrefs?还是需要decode_json在两次哈希之后运行?
while(my($k,$v) = each(%$json1)) {
$copy->{ NFD($k) } = NFD($v);
}
Run Code Online (Sandbox Code Playgroud)
简而言之:
$href?有可能实现更好一些,因为明确地做NFD每个key value和创建另一个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
Run Code Online (Sandbox Code Playgroud)
在为您的问题搜索正确的解决方案时,我发现:该软件是 c*rp :) 请参阅:https ://stackoverflow.com/a/17448888/632407 。
无论如何,找到了您的特定问题的解决方案 - 如何读取带有文件名的 json,无论标准化如何:
而不是你的:
#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" ;
Run Code Online (Sandbox Code Playgroud)
使用下一个:
#now read them
my $jc = get_json_from_utf8_file('nfc.json') ;
my $jd = get_json_from_utf8_file('nfd.json') ;
...
sub get_json_from_utf8_file {
my $file = shift;
return
decode_json #let parse the json to perl
encode 'utf8', #the decode_json want utf8 encoded binary string, encode it
NFC #conv. to precomposed normalization - regardless of the source
read_file #your file contains utf8 encoded text, so read it correctly
$file, { binmode => ':utf8' } ;
}
Run Code Online (Sandbox Code Playgroud)
这应该(至少我希望)确保无论什么分解使用 JSON 内容,NFC都会将其转换为预组合版本,并且 JSON:XS 会将其正确读取解析为相同的内部 perl 结构。
所以你的例子打印:
something
Run Code Online (Sandbox Code Playgroud)
无需遍历$json
这个想法来自约瑟夫·迈尔斯和尼莫;)
也许一些更熟练的程序员会给出更多提示。
| 归档时间: |
|
| 查看次数: |
386 次 |
| 最近记录: |