2010-06-10 37 views
3

我正在尝试读取只有CR作为行分隔符的文件。我正在使用Mac OS X和Perl v.5.8.8。此脚本应该在每个平台上运行,用于每种类型的行分隔符(CR,LF,CRLF)。如何逐行读取一个仅限CR的文件与Perl?

我当前的代码如下:

open(FILE, "test.txt"); 

while($record = <FILE>){ 
    print $record; 
} 

close(TEST); 

目前这仅打印最后一行(或最差)。到底是怎么回事? 显然,我想不转换文件。可能吗?

+4

我会很烦人,并建议您使用'strict'和'warnings'编译指示,它们会为您节省数小时的调试时间。另外,最好使用带词法文件句柄的现代3参数形式。有关更多信息,请参阅http://stackoverflow.com/questions/1479741/why-is-three-argument-open-calls-with-lexical-filehandles-a-perl-best-practice。 – daotoad 2010-06-10 22:32:06

+0

@daotoad谢谢 – subb 2010-06-29 12:27:58

回答

19

可以使用特殊变量$/设置分隔符:

local $/ = "\r" # CR, use "\r\n" for CRLF or "\n" for LF 
my $line = <FILE>; 

进一步的信息,请参阅perldoc perlvar

与各种换行符作品另一个解决方案是在一次啜整个文件,然后使用正则表达式将其分割成线:

local $/ = undef; 
my $content = <FILE>; 
my @lines = split /\r\n|\n|\r/, $content; 

你不应该这样做虽然有非常大的文件,因为文件被完全读入内存。请注意,将$ /设置为未定义值会禁用行分隔符,这意味着所有内容都会被读取直到文件结束。

+0

似乎没有用... – subb 2010-06-10 20:12:19

+0

“\ r”只是CR的一个例子,您可能想分别尝试使用“\ r \ n”和“\ n”作为CRLF和LF。 – jkramer 2010-06-10 20:13:24

+0

哦,我明白了。 CR和终端不能一起玩。 – subb 2010-06-10 20:21:52

1

我解决了,可能是这里有用的一个更一般的问题:

如何分析大文件中的行由行与任何行分隔符(CR/CRLF/LF),但事先未知。

'Big'文件意味着将整个文件读入一个变量是不行的。这里函数'detectEndOfLine'获取文件的名称并返回'\ r'或'\ n',无论用于行结束符(从\ n开始搜索'\ r'或'\ n'符号char-by-char文件结尾)。

my $file = "test.txt"; 
local $/ = detectEndOfLine($file); 
open(IN, $file) or die "Can't open file \"$file\" for reading: $!\n"; 
while(<IN>) { 
    s/\r\n|\n|\r$//; 
    print "$_\n"; 
} 

sub detectEndOfLine { 
    my $file = $_[0]; 
    my $size = -s $file; 
    print "\"$size\"\n"; 

    open(IN, $file) or die "Can't open file \"$file\" for reading: $!\n"; 
    for(my $i = $size; $i >= 0; --$i) { 
     seek(IN, $i, 0); 
     $_ = <IN>; 
     my $sym = substr($_, 0, 1); 
     return $sym if($sym eq "\n" or $sym eq "\r"); 
    } 
    return undef; 
}