我有一个文件,其中每行都有一个短语/术语,我从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 resolve
我该怎么办?
答案 0 :(得分:4)
我强烈建议您创建一个过滤器,该过滤器将带有混合编码行的文件转换为纯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
中列出它们。
答案 1 :(得分:3)
它的工作原理如下:
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 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";
}
。
根据tchrist的声音建议进行更新:
{{1}}