计算由Perl中的CR / LF(回车符和换行符)分隔的记录

时间:2013-05-18 16:00:07

标签: perl

我正在尝试创建一个简单的脚本来读取包含书名记录的文本文件。每个记录用一个普通的旧双空格(\r\n\r\n)分隔。我需要计算文件中有多少条记录。

例如,这里是输入文件:

record 1
some text


record 2 
some text
...

我正在使用正则表达式来检查回车和换行符,但它无法匹配。我究竟做错了什么?我的智慧结束了。

sub readInputFile {

    my $inputFile = $_[0]; #read first argument from the commandline as fileName

    open INPUTFILE, "+<", $inputFile or die $!;    #Open File

    my $singleLine;
    my @singleRecord;
    my $recordCounter = 0;

    while (<INPUTFILE>) {                    # loop through the input file line-by-line
        $singleLine = $_;
        push(@singleRecord, $singleLine);    # start adding each line to a record array

        if ($singleLine =~ m/\r\n/) {        # check for carriage return and new line
            $recordCounter += 1;
            createHashTable(@singleRecord);  # send record make a hash table
            @singleRecord = ();              # empty the current record to start a new record
        }

    }

    print "total records : $recordCounter \n";
    close(INPUTFILE);
}

3 个答案:

答案 0 :(得分:1)

听起来您正在Linux上处理Windows文本文件,在这种情况下,您要打开包含:crlf图层的文件,该图层会将所有CRLF行结尾转换为标准Perl {{1}结束。

如果您正在Windows平台上阅读Windows文件,那么转换已经为您完成,您将无法在已阅读的数据中找到CRLF序列。如果您正在阅读Linux文件然后在那里没有CR字符。

听起来你的记录也是用空行分隔的。将内置输入记录分隔符变量\n设置为空字符串将导致Perl一次读取整个记录。

我相信您的子程序的这个版本就是您所需要的。请注意,熟悉Perl的人会感谢您使用小写字母和下划线表示变量和子例程名称。通常为包名称保留混合大小写。

您没有显示$/因此我无法确定它需要哪些数据。我已经将记录扼杀并分成了几行,并在删除换行符的情况下传递了记录中的行列表。将整个记录作为单个字符串传递可能会更好,并让create_hash_table根据需要对其进行处理。

create_hash_table

答案 1 :(得分:0)

您可以通过更改Perl的记录分隔符来更简洁地执行此操作,这将使循环一次返回记录而不是一次返回一行。

E.g。打开文件后:

local $/ = "\r\n\r\n";
my $recordCounter = 0;
$recordCounter++ while(<INPUTFILE>);    

$/拥有Perl的全局记录分隔符,并使用local进行范围设置允许您暂时覆盖其值,直到封闭块结束,此时它将自动恢复为其先前的值。

但听起来你正在处理的文件可能实际上有“\ n \ n”记录分隔符,甚至“\ r \ n”。您需要为正在处理的文件正确设置记录分隔符。

答案 2 :(得分:0)

如果您的文件不是很大的千兆字节文件,那么最简单,最安全的方法就是读取整个文件,然后使用generic newline metacharacter tidyverse

这样,如果某些文件实际使用LF而不是CRLF(甚至是旧的Mac标准CR),它也可以工作。

如果您还需要实际记录,请与library(tidyverse) df1 %>% left_join(df2) %>% group_by(scientific_name) %>% arrange(scientific_name, desc(total)) %>% slice(1:n.at.70[1]) 一起使用:

\R

或者如果您只想对记录进行计数:

split

有关更多详细信息,另请参见我对类似问题的other answer here