我有两个来自不同操作系统的 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
和来自 JSON::XS
的 decode_json .将 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
为我产生相同的输出。
现在的问题:
$hashrefs
? 或者需要
decode_json
之后在两个哈希上运行类似的东西?while(my($k,$v) = each(%$json1)) {
$copy->{ NFD($k) } = NFD($v);
}
简而言之:
$href
中读取不同的 JSON 文件以获得相同的规范化?显式执行 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
最佳答案
在为您的问题寻找正确的解决方案时,我发现:该软件是 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" ;
使用下一个:
#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' } ;
}
这应该(至少我希望)确保而不考虑什么分解使用 JSON 内容,
NFC
会将其转换为预先组合的版本,并且 JSON:XS 将正确读取并将其解析为相同的内部 perl 结构。所以你的例子打印:
something
无需遍历
$json
这个想法来自约瑟夫迈尔斯和尼莫;)
也许一些更熟练的程序员会给出更多的提示。
关于json - 使用 perl 对存储在 JSON 中的 utf8 文件名进行规范化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17434027/