如何读取具有不同行分隔符的大文件?

时间:2013-06-03 20:12:51

标签: perl

我有两个非常大的XML文件,它们具有不同类型的行结尾。 文件A在每个XML记录的末尾都有CR LF。文件B在每个XML记录的末尾只有CR。

为了正确读取文件B,我需要将内置的Perl变量$ /设置为“\ r”。 但是,如果我在文件A中使用相同的脚本,则脚本不会读取文件中的每一行,而是将其作为单行读取。

如何使脚本与具有各种行结束分隔符的文本文件兼容?在下面的代码中,脚本正在读取XML数据,然后使用正则表达式根据特定的XML标记记录结束标记(如< \ record>)拆分记录。最后,它将请求的记录写入文件。

 open my $file_handle, '+<', $inputFile or die $!;  
local $/ = "\r";
while(my $line = <$file_handle>) { #read file line-by-line. Does not load whole file into memory.
    $current_line = $line;

    if ($spliceAmount > $recordCounter) { #if the splice amount hasn't been reached yet
        push (@setofRecords,$current_line); #start adding each line to the set of records array
        if ($current_line =~ m|$recordSeparator|) { #check for the node to splice on
            $recordCounter ++; #if the record separator was found (end of that record) then increment the record counter
        }
    } 
    #don't close the file because we need to read the last line

}
$current_line =~/(\<\/\w+\>$)/;
$endTag = $1;
print "\n\n";
print "End Tag: $endTag \n\n";

close $file_handle;

2 个答案:

答案 0 :(得分:1)

虽然理论上你可能不需要它来解析.xml,你应该使用xml解析器。我建议使用XML::LibXM或者从XML::Simple开始。

答案 1 :(得分:0)

如果文件不是太大而无法保存在内存中,您可以将整个事物篡改为标量,并使用适当灵活的正则表达式将其分成正确的行。例如,

local $/ = undef;
my $data = <$file_handle>;
my @lines = split /(?>\r\n)|(?>\r)|(?>\n)/, $data;
foreach my $line (@lines) {
    ...
}

使用前瞻断言(?>...)会保留常规<>运算符之类的行尾字符。无论如何,如果你只是想要扼杀他们,你可以通过将/\r\n|\r|\n/传递给split来为自己节省一步。