簡體   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