2016-07-26 83 views
1

我有一个问题,我无法以适合于Stackoverflow的方式重现,尽管它在我的可重现生产环境。

问题occors在一个Perl脚本,除其他外,遍历一个文件,看起来像这样:

abc-4-9|free text, possibly containing non-ascii characters| 
cde-3-8|hällo wörld| 
# comment 

xyz-9-1|and so on| 
qrs-2-8|and so forth| 

我可以验证这个Perl脚本文件的正确性:

use warnings; 
use strict; 

open (my $f, '<:encoding(UTF-8)', 'c:\path\to\file') or die "$!"; 

while (my $s = <$f>) { 
    chomp($s); 
    next unless $s; 
    next if $s =~ m/^#/; 
    $s =~ m!(\w+)-(\d+)-(\d+)\|([^|]*)\|! or die "\n>$s<\n didn't match on line $."; 
} 

print "Ok\n"; 
close $f; 

当我运行这个脚本时,它不会死于第10行,因此打印Ok

现在,我在一个巨大的Perl脚本中使用基本相同的构造(因此对于Stackoverflow而言是不可再生的),它将死于输入文件的第2199行。

如果我改变的东西,从第一行(这是完全无关的行2199)像

www-1-1|A line with some words| 

www-1-1|x| 

脚本将处理线2199(但是后来失败)。

有趣的是,当我改变

open (my $f, '<', 'c:\path\to\file') or die "$!"; 

open (my $f, '<:encoding(UTF-8)', 'c:\path\to\file') or die "$!"; 

没有:encoding(UTF-8)指令,此行为已出台,该脚本不会失败。当然,我需要编码指令,因为该文件包含非ASCII字符。

顺便说一句,同样的脚本在Linux上运行没有问题。

在Windows上,它失败了,我用草莓的Perl 5.24

+0

该文件没有BOM。由于它包含机密数据,所以我不能不幸的只是复制并粘贴前几行。 –

+1

添加'使用Devel :: Peek;'并用'Dump($ s)替换'die ...',死...'。请提供输出。 – ikegami

+0

或者,用'do {use Data :: Dumper; local $ Data :: Dumper :: Useqq = 1; die Dumper($ s)'替换'die ...''。 “。(utf8 :: is_utf8($ s)?1:0)。”在$行。不匹配“};' – ikegami

回答

2

我没有为什么,这是必要的充分和正确的解释,但你可以尝试打开文件

'<:unix:encoding(UTF-8)' 

这可能与我的问题“Why is CRLF set for the unix layer on Windows?”有关,当我试图找出那些我从未想到的东西时,我注意到了它。