我有兩個來自不同操作系統的Json文件。使用perl存儲在JSON中的utf8文件名的規範化
這兩個文件都編碼在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
相同正常化?如果明確地對每個key
value
執行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
同時發現自己正是這個解決方案,謝謝。 – kobame