我正在尝试创建一个简单的脚本来读取包含书名记录的文本文件。每个记录用一个普通的旧双空格(\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);
}
答案 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。