【问题标题】:Script extracts and prints UTF-8 words well, but prints JSON as garbage脚本很好地提取和打印 UTF-8 单词,但将 JSON 打印为垃圾
【发布时间】:2015-06-07 04:54:59
【问题描述】:

我已经在 Mac OS Mavericks (perl 5.16.2) 和 Yosemite 以及 Windows 7 (strawberry-perl-5.20.1.1-64bit-portable) 上尝试了我的脚本。

它应该读取 UTF-8 数据(俄语文本)并将其放入数据结构中 - 最后将数据结构打印为 JSON 字符串(输出将用于在 iOS 文字游戏中提供 Core Data)。

第一部分有效(提取单词并打印它们 - 进行验证)效果很好,但最后部分无效:生成的 JSON 字符串包含垃圾:

有人知道如何修复我的简单测试脚本吗?

#!/usr/bin/perl -w

use strict;
use warnings;
use utf8;
use JSON;

binmode(STDOUT, ':utf8');

my $root = { words => [] };

while (<DATA>) {
        chomp;
        utf8::decode($_);
        my @a = split /\s*[:,]\s*/;

        my $words = [];
        for my $word (@a[1 .. $#a]) {
                print "WORD: $word\n";
                #push @$words, utf8::encode($word);
                push @$words, $word;
        }

        push @{$root->{words}}, $words;
}

print to_json($root, {utf8 => 1, pretty => 1});

__DATA__
Голова: небо, язык, мозг, глотка, надгортанник, пищевод, горло, гортань
Сумки: портмоне, кошелек, портфель, рюкзак, лямка, застежка

【问题讨论】:

  • PS - utf8::decode($_); 不应该在那里,因为 use utf8; 已经解码了源代码(包括数据)。它目前正在失败(默默地),但它可能会破坏您的数据。
  • 实际上在我的真实脚本中我没有阅读&lt;DATA&gt;,而是使用while (&lt;&gt;) 阅读另一个文件,这就是为什么我添加了utf8::decode($_) 以便正则表达式在读取的行上工作。
  • 使用use open ':std', ':encoding(UTF-8)';。它对 STDIN 进行解码,对 STDOUT 和 STDERR 进行编码,并为在其词法范围内打开的文件设置默认编码。这包括使用&lt;&gt; 打开的那些。

标签: json perl utf-8


【解决方案1】:

你是双重编码。您正在使用from_json (utf8 =&gt; 1) 进行编码,然后在输出到STDOUT (binmode(STDOUT, ':utf8');) 时再次进行编码。

解决方案不清楚,因为不清楚您要达到的目标。如果你真的要输出非 JSON 和 JSON 到 STDOUT,不要让from_json 编码。

【讨论】:

    【解决方案2】:

    输出看起来“错误”,但没关系:它已编码。要正确查看,只需设置

    binmode STDOUT, ':raw';
    

    在打印 JSON 之前。

    您可以使用encode_json 来简化脚本:

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    use utf8;
    use JSON;
    
    binmode(STDIN, ":utf8");
    binmode(STDOUT, ":utf8");
    
    my $root;
    
    while (<DATA>) {
            chomp;
            my @words = split /\s*[:,]\s*/;
            push @{ $root->{words} }, [];
    
            for my $word (@words[1 .. $#words]) {
                    print "WORD: $word\n";
                    push @{ $root->{words}[-1] }, $word;
            }
    }
    
    my $json = encode_json($root);
    binmode STDOUT, ':raw';
    print $json;
    

    【讨论】:

    • 他的代码也可以,如果他在binmode(STDOUT, ":utf8");之后添加binmode STDOUT, ':raw';
    • 如果我添加binmode(STDOUT, ":raw");,那么当我将脚本输出重定向到文件时,它确实有效。有警告Wide character in print,但生成的文件没问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-08
    • 2019-11-26
    • 2017-07-21
    • 2013-12-23
    相关资源
    最近更新 更多