在Perl中转换为unicode字符?

时间:2014-09-22 10:47:43

标签: perl unicode

我想在Perl中将文本(印地语)转换为Unicode。我在CPAN中搜索过。但是,我找不到我想要的确切模块/方式。基本上,我正在寻找像this这样的东西。

我的输入是:

इस परीक्षण के लिए है

我的预期输出是:

\u0907\u0938\u0020\u092a\u0930\u0940\u0915\u094d\u0937\u0923\u0020\u0915\u0947\u0020\u0932\u093f\u090f\u0020\u0939\u0948

如何在Perl中实现这一目标?

给我一​​些建议。

4 个答案:

答案 0 :(得分:8)

试试这个

use utf8;

my $str = 'इस परीक्षण के लिए है';

for my $c (split //, $str) {
    printf("\\u%04x", ord($c));
}
print "\n";

答案 1 :(得分:5)

你真的不需要任何模块来做到这一点。 ord用于提取字符代码,printf用于将其格式化为4位数的零填充十六进制绰绰有余:

use utf8;
my $str = 'इस परीक्षण के लिए है';
(my $u_encoded = $str) =~ s/(.)/sprintf "\\u%04x", ord($1)/sge;
# \u0907\u0938\u0020\u092a\u0930\u0940\u0915\u094d\u0937\u0923\u0020\u0915\u0947\u0020\u0932\u093f\u090f\u0020\u0939\u0948

答案 2 :(得分:4)

如果您只想要一个简单的转换器,可以使用以下过滤器

perl -CSDA -nle 'printf "\\u%*v04x\n", "\\u",$_'
#or
perl -CSDA -nlE 'printf "\\u%04x",$_ for unpack "U*"'

像:

echo "इस परीक्षण के लिए है" | perl -CSDA -ne 'printf "\\u%*v04x\n", "\\u",$_'
#or
perl -CSDA -ne 'printf "\\u%*v04x\n", "\\u",$_' <<<  "इस परीक्षण के लिए है"

打印:

\u0907\u0938\u0020\u092a\u0930\u0940\u0915\u094d\u0937\u0923\u0020\u0915\u0947\u0020\u0932\u093f\u090f\u0020\u0939\u0948\u000a

具有代理对的Unicode。

use strict;
use warnings;
use utf8;
use open qw(:std :utf8);

my $str = "if( \N{U+1F42A}+\N{U+1F410} == \N{U+1F41B} ){ \N{U+1F602} = \N{U+1F52B} } # ορισμός ";

print "$str\n";
for my $ch (unpack "U*", $str) {
        if( $ch > 0xffff ) {
                my $h = ($ch - 0x10000) / 0x400 + 0xD800;
                my $l = ($ch - 0x10000) % 0x400 + 0xDC00;
                printf "\\u%04x\\u%04x", $h, $l;
        }
        else {
                printf "\\u%04x", $ch;
        }
}
print "\n";

打印

if( + ==  ){  =  } # ορισμός 
\u0069\u0066\u0028\u0020\ud83d\udc2a\u002b\ud83d\udc10\u0020\u003d\u003d\u0020\ud83d\udc1b\u0020\u0029\u007b\u0020\ud83d\ude02\u0020\u003d\u0020\ud83d\udd2b\u0020\u007d\u0020\u0023\u0020\u03bf\u03c1\u03b9\u03c3\u03bc\u03cc\u03c2\u0020

答案 3 :(得分:3)

因为我就其他答案如何达不到各种工具的期望留下了一些评论,我想分享一个解决方案,将基本多语言平面之外的字符编码为两个转义对:{ {1}}将成为""

这是通过以下方式完成的:

  1. 将字符串编码为UTF-16,没有字节顺序标记。我们明确选择了一个结尾。在这里,我们任意使用big-endian形式。这会产生一串八位字节(“字节”),其中两个八位字节组成一个UTF-16代码单元,两个四个八位字节代表一个Unicode代码点。

    这样做是为了方便和表现;我们也可以自己确定UTF-16代码单元的数值。

  2. \ud83d\ude03生成的二进制字符串为16位整数,代表每个UTF-16代码单元。我们必须尊重正确的字节顺序,因此我们对unpack使用n*模式(即16位大端无符号整数)。

  3. 将每个代码单元格式化为unpack转义。

  4. 作为Perl子程序,这看起来像

    \uxxxx

    测试用例:

    use strict;
    use warnings;
    use Encode ();
    
    sub unicode_escape {
        my ($str) = @_;
        my $UTF_16BE_octets = Encode::encode("UTF-16BE", $str);
        my @code_units = unpack "n*", $UTF_16BE_octets;
        return join '', map { sprintf "\\u%04x", $_ } @code_units;
    }