我有一些文本文件,我试图用Windows上的Perl脚本进行转换。在Notepad +中文本文件看起来很正常,但我脚本中的所有正则表达不匹配。然后我注意到当我在NotePad +中打开文本文件时,状态栏显示“UCS-2 Little Endia”(原文如此)。我假设这对应于编码UCS-2LE。所以我在Perl中创建了“readFile”和“writeFile”subs,就像这样:
use PerlIO::encoding;
my $enc = ':encoding(UCS-2LE)';
sub readFile {
my ($fName) = @_;
open my $f, "<$enc", $fName or die "can't read $fName\n";
local $/;
my $txt = <$f>;
close $f;
return $txt;
}
sub writeFile {
my ($fName, $txt) = @_;
open my $f, ">$enc", $fName or die "can't write $fName\n";
print $f $txt;
close $f;
}
my $fName = 'someFile.txt';
my $txt = readFile $fName;
# ... transform $txt using s/// ...
writeFile $fName, $txt;
现在正则表达式匹配(尽管比我预期的要少),但是输出包含长串的亚洲字符,其中散布着正确文本的长字符串。我的代码错了吗?或许Notepad +编码错误?我该怎么办?
答案 0 :(得分:2)
好的,我明白了。问题是由“打开”调用的“encoding ...”参数完成的编码转换与Windows上Perl完成的默认CRLF转换之间的断开引起的。似乎正在发生的事情是,在编码已经完成之后输出的LF被转换为CRLF,这导致了下一行的16位编码的“奇偶校验”。一旦到达下一行,“平价”就会被收回。这可以解释“长长的亚洲人物串穿着正确文字的长串”......其他每一行都被搞砸了。
为了纠正它,我在“打开”调用中取出了编码参数,并添加了一个“binmode”调用,如下所示:
open my $f, $fName or die "can't read $fName\n";
binmode $f, ':raw:encoding(UCS-2LE)';
binmode显然有一个“分层”I / O处理的概念,这有点复杂。
我无法弄清楚的一件事是如何恢复我的CRLF翻译。如果我遗漏:raw或add:crlf,“奇偶校验”问题会返回。我也尝试过重新订购,无法让它发挥作用。
(我将此作为一个单独的问题添加:CRLF translation with Unicode in Perl)
答案 1 :(得分:1)
我没有要检查记事本+编辑器,但可能是BOM输出编码不包含BOM的问题。
http://perldoc.perl.org/Encode/Unicode.html#Size%2c-Endianness%2c-and-BOM
也许您需要使用字节顺序标记对$ txt进行编码,如上所述。