json - 使用 perl 对存储在 JSON 中的 utf8 文件名进行规范化

标签 json perl utf-8

我有两个来自不同操作系统的 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

为我产生相同的输出。

现在的问题:
  • 如何简单读取两个 json 文件以获得相同的规范化到两个 $hashrefs ?

  • 或者需要decode_json之后在两个哈希上运行类似的东西?
    while(my($k,$v) = each(%$json1)) {
        $copy->{ NFD($k) } = NFD($v);
    }
    

    简而言之:
  • 如何在 perl $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/

    相关文章:

    ruby - 如何使用 rails 仅查找 google 加一计数(不需要按钮和 g +1 图像)

    php - OpenWeatherMap API 生成不正确的输出

    JSON 在 Perl 中编码/解码 utf8 字符串

    perl - 如何从 Vim 脚本中的 Perl 方法返回值?

    mysql - 使用 Perl 更改日期格式

    mysql - 哪个 UTF8 - phpMyAdmin 可以正确显示中文、俄文、阿拉伯文?

    java - 为什么我不能在 Java 的 char 数组中存储日文 UTF-8 字符?

    javascript - 如何循环遍历所有对象数组?

    c# - 首次显示后如何重置jit treemap控件?

    python - 相当于 python 在 golang 中的编码 ('utf8' )