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