繁体   English   中英

Perl - 文件编码和单词比较

[英]Perl - File Encoding and Word Comparison

我有一个文件,每行有一个短语/术语,我从STDIN读到perl。 我有一个停用词列表(如“á”,“são”,“é”),我希望将每个词与每个词进行比较,如果它们相等则删除。 问题是我不确定文件的编码格式。

我从file命令得到这个:

words.txt: Non-ISO extended-ASCII English text

我的linux终端是UTF-8,它显示了某些单词的正确内容,而其他单词则没有。 以下是其中一些的输出:

condi<E3>
conte<FA>dos
ajuda, mas não resolve
mo<E7>ambique
pedagógico são fenómenos

您可以看到第3行和第5行正确识别带有重音符和特殊字符的单词,而其他行则没有。 其他行的正确输出应为:condiã,conteúdos和moçambique。

如果我使用binmode(STDOUT, utf8) ,“错误”行现在正确输出而其他行不正确。 例如第3行:

ajuda,masnão决心

我该怎么办?

我强烈建议您创建一个过滤器,该过滤器将带有混合编码行的文件转换为纯UTF-8。 然后改为

open(INPUT, "< badstuff.txt") || die "open failed: $!";

你可以打开固定版本,或从修复程序打开管道,如:

open(INPUT, "fixit < badstuff.txt |") || die "open failed: $!"

无论哪种情况,你都会

binmode(INPUT, ":encoding(UTF-8)") || die "binmode failed";

然后fixit程序可以这样做:

use strict;
use warnings;
use Encode qw(decode FB_CROAK);

binmode(STDIN,  ":raw")  || die "can't binmode STDIN";
binmode(STDOUT, ":utf8") || die "can't binmode STDOUT";

while (my $line = <STDIN>) {
    $line = eval { decode("UTF-8", $line, FB_CROAK() };
    if ($@) { 
        $line = decode("CP1252", $line, FB_CROAK()); # no eval{}!
    }
    $line =~ s/\R\z/\n/;  # fix raw mode reads
    print STDOUT $line;    
}

close(STDIN)  || die "can't close STDIN: $!";
close(STDOUT) || die "can't close STDOUT: $!";
exit 0;

看看它是如何工作的? 当然,您可以将其更改为默认为其他一些编码,或者具有多个后退。 可能最好在@ARGV列出它们。

它的工作原理如下:

C:\Dev\Perl :: chcp
Aktive Codepage: 1252.

C:\Dev\Perl :: type mixed-encoding.txt
eins zwei drei Käse vier fünf Wurst
eins zwei drei Käse vier fünf Wurst

C:\Dev\Perl :: perl mixed-encoding.pl < mixed-encoding.txt
eins zwei drei vier fünf
eins zwei drei vier fünf

mixed-encoding.pl的位置如下:

use strict;
use warnings;
use utf8; # source in UTF-8
use Encode 'decode_utf8';
use List::MoreUtils 'any';

my @stopwords = qw( Käse Wurst );

while ( <> ) { # read octets
    chomp;
    my @tokens;
    for ( split /\s+/ ) {
        # Try UTF-8 first. If that fails, assume legacy Latin-1.
        my $token = eval { decode_utf8 $_, Encode::FB_CROAK };
        $token = $_ if $@;
        push @tokens, $token unless any { $token eq $_ } @stopwords;
    }
    print "@tokens\n";
}

请注意,脚本不必以UTF-8编码。 只是如果你的脚本中有时髦的字符数据,你必须确保编码匹配,所以如果你的编码是UTF-8,请use utf8如果你的编码不​​是,则use utf8

根据tchrist的声音建议更新:

use strict;
use warnings;
# source in Latin1
use Encode 'decode';
use List::MoreUtils 'any';

my @stopwords = qw( Käse Wurst );

while ( <> ) { # read octets
        chomp;
        my @tokens;
        for ( split /\s+/ ) {
                # Try UTF-8 first. If that fails, assume 8-bit encoding.
                my $token = eval { decode utf8 => $_, Encode::FB_CROAK };
                $token    = decode Windows1252 => $_, Encode::FB_CROAK if $@;
                push @tokens, uc $token unless any { $token eq $_ } @stopwords;
        }
        print "@tokens\n";
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM