HTML ::实体格式化问题?

时间:2017-03-21 11:08:56

标签: perl unicode

我尝试在perl中解码HTML字符以及\u字符。所以我试过,下面的一个

use Encode;
use HTML::Entities;

my $cont= do{local $/; <DATA> };
$cont=Remove_Spaces($cont);
print "$cont\n";
sub Remove_Spaces
{
    my $clean=shift;
    $clean =~s/\\u00(\w{2})/encode("utf-8",chr(hex($1)))/egs;
    #$clean=~s/(\&\#?\w+\;)/decode_entities($1)/egs;
    $clean=~s/^\s+|\s+$//igs;
    $clean=~s/\s+/ /igs;
    return $clean;
}

__DATA__
sympa et comp\u00e9ten c\u00e2ble 19&euro; e

我期待输出

sympa et compéten câble 19€ some data

但是当我用HTML :: Entities运行脚本时,它会得到如下结果,

sympa et compéten câble 19€ e

以上输出的unicode字符都是错误格式化的。

当我评论HTML :: Entities时,它会给出以下结果,

sympa et compéten câble 19&euro; e

以上输出实体字符均未格式化。

我不知道这里有什么问题。

我也尝试过单字符替换(同样的RegEx替换)

sub Remove_Spaces
{
    my $clean=shift;
    $clean=~s/\s*<[^>]*?>\s*/ /igs;
    while($clean=~m/(\&\#?\w+\;)/igs)
    {
        my $find    = $1;
        my $replace = decode_entities($find);
        my $pos = index($clean, $find);
        while($pos > -1) 
        {
            substr($clean, $pos, length($find), $replace);
            $pos = index($clean, $find, $pos + length($replace));
        }
    }

    while($clean=~m/(\\u00(\w{2}))/igs)
    {
        my $find    = $1;

        my $replace = encode("utf8",chr(hex($2)));
        #print ord($replace),"\t$replace***\n";     

        my $pos = index($clean, $find);
        while($pos > -1) 
        {
            substr($clean, $pos, length($find), $replace);

            $pos = index($clean, $find, $pos + length($replace));
        }
    }

    $clean=~s/^\s+|\s+$//igs;
    $clean=~s/\s+/ /igs;
    return $clean;
}

在上面的代码中,我只使用substr替换一个字符。那为什么会影响\u个字符?

我该如何解决?

1 个答案:

答案 0 :(得分:0)

chr内置函数已经在Perl的内部编码中返回Unicode字符,因此您在这里使用encode不正确。如果有的话,你会解码你的输入数据,但这里也不正确。

我删除了对encode的调用,并进行了一些其他微小的更改,例如在整个字符串上调用decode_entities而不是通过可执行替换选择性地进行调整。

use strict;
use warnings;

use HTML::Entities;

sub Remove_Spaces {
    my $clean = shift;
    $clean =~ s/\\u00(\w{2})/chr(hex($1))/eg;  # match should probably be: ([0-9a-f]{2})
    $clean =~ s/^\s+|\s+$//g;
    $clean =~ s/\s+/ /g;
    return decode_entities($clean);
}

my $cont = do { local $/; <DATA> };
$cont = Remove_Spaces($cont);
binmode(STDOUT, ':encoding(utf8)');  # avoid 'wide character in print' warnings
print "$cont\n";

__DATA__
sympa et comp\u00e9ten c\u00e2ble 19&euro; e

输出:

sympa et compéten câble 19€ e