[英]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.