'子程序条目中的宽字符“ - UTF-8编码的西里尔字作为字节序列

时间:2015-08-29 12:15:42

标签: perl unicode utf-8 md5 cyrillic

我正在开发一个带有大字典的Android文字游戏 -

app screenshot

单词(超过700 000)在文本文件中保存为单独的行(然后放入SQLite数据库中)。

为了防止竞争对手提取我的字典,我想用md5编码长度超过3个字符的所有单词。 (我不会使用罕见的俄语字母ъэ来混淆简短的单词和单词,因为我想在我的应用程序中列出它们。)

所以这是我尝试在Mac Yosemite上使用 perl v5.18.2 运行的脚本:

#!/usr/bin/perl -w

use strict;
use utf8;
use Digest::MD5 qw(md5_hex);

binmode(STDIN, ":utf8");
#binmode(STDOUT, ":raw");
binmode(STDOUT, ":utf8");

while(<>) {
        chomp;
        next if length($_) < 2; # ignore 1 letter junk
        next if /жы/;           # impossible combination in Russian
        next if /шы/;           # impossible combination in Russian

        s/ё/е/g;

        #print "ORIGINAL WORD $_\tENCODED WORD: ";

        if (length($_) <= 3 || /ъ/ || /э/) { # do not obfuscate short words
                print "$_\n";                # and words with rare letters
                next;
        }

        print md5_hex($_) . "\n";            # this line crashes
}

正如您所看到的,我必须在我的Perl脚本的源代码中使用西里尔字母 - 这就是我将use utf8;置于其顶部的原因。

然而我真正的问题是length($_)报告的值太高(可能是报告字节数而不是字符数)。

所以我尝试添加:

binmode(STDOUT, ":raw");

或:

binmode(STDOUT, ":utf8");

但是脚本会在print md5_hex($_)的行中以子例程条目中的宽字符而死亡。

请帮我修复我的剧本。

我将其视为:

perl ./generate-md5.pl < words.txt > encoded.txt

以下是示例 words.txt 数据,以方便您使用:

а
аб
абв
абвг
абвгд
съемка

4 个答案:

答案 0 :(得分:13)

md5_hex需要一串字节用于输入,但您要传递一个已解码的字符串(一串Unicode代码点)。显式编码字符串。

use strict;
use utf8;
use Digest::MD5;
use Encode;
# ....
# $_ is assumed to be utf8 encoded without check
print Digest::MD5::md5_hex(Encode::encode_utf8($_)),"\n";
# Conversion only when required:
print Digest::MD5::md5_hex(utf8::is_utf8($_) ? Encode::encode_utf8($_) : $_),"\n";

答案 1 :(得分:4)

  

我真正的问题是长度($ _)报告的值太高

是的,您正在阅读ARGV文件句柄,并且未将其编码设置为UTF-8

您可以使用open pragma来解决此问题。而不是所有binmode语句,请使用

use open qw/ :std :encoding(utf8) /;

会将所有文件句柄的默认打开模式(包括标准文件句柄)更改为:encoding(utf8)

答案 2 :(得分:1)

如果你使用 Mojolicious 那么将 to_json 替换为 encode_json 将解决问题。

来自 JSON 模块的文档,to_json 关键字: 如果您想编写与外部世界通信的现代 perl 代码,您应该使用 encode_json(假设 JSON 数据以 UTF-8 编码)。 我无法预见一个非 UTF-8 的世界。

答案 3 :(得分:1)

如果您使用的是 perl 5.0 及更高版本,则可以通过将 to_json 更改为 encode_json 来解决此问题