我有一个包含文字的CSV文件,其中包含新的换行符。例如
1,b,hello
world,x
2,a,hello
mars,y
要一次连续读取所有内容,我想为$ / special变量指定一个正则表达式。关于我如何做到这一点的任何建议?
我的想法是,如果我为我的特殊变量添加类似“(x | y)\ n”的内容,它应该捕获行以x或y结尾的情况以及新行。
由于
答案 0 :(得分:4)
你不能使用正则表达式来$ /。但是,如果文件不是太大,您可以将整个内容读入标量并在正则表达式上拆分。
@records = split /(x|y)\n/, $data;
答案 1 :(得分:3)
没有将这样的文件分成记录的一般方法,因为无法判断文件中的行是更多是当前记录还是新记录的开头。
但是如果你可以假设
记录
字段中的数据从不包含逗号
记录的最后一个字段永远不会分成行
然后您可以简单地累积文件中的行,直到您有足够数量的字段
该计划证明了这一原则。
use strict;
use warnings;
while (my $record= <>) {
$record .= <> until $record =~ tr/,// == 3;
print ">> $record\n";
}
<强>输出强>
>> 1,b,hello
world,x
>> 2,a,hello
mars,y
答案 2 :(得分:2)
您可以创建自己的子,以便在以后读取一个数据集:
sub readDataSet {
my $buffer = '';
local $/ = "\n";
$buffer .= <STDIN> until $buffer =~ /(x|y)\n$/;
return $buffer;
}
my $nextRow = readDataSet();
这将返回整行。我可以这样做,因为你的Regexp以一个不变的部分结束。这个子有几种变化:
从任何文件句柄中读取:
sub readDataSet {
my ($filehandle) = @_;
my $buffer = "";
$buffer .= <$filehandle> until $buffer =~ /(x|y)\n$/;
return $buffer;
}
open my $fh, "<", $filename or die;
my $nextRow = readDataSet($fh);
构造一个执行阅读的匿名子。 Filehandle仅在构造函数sub中提供一次。这有点面向对象。
sub newDataSetReader {
my ($filehandle) = @_;
return sub {
my $buffer = '';
local $/ = "\n";
$buffer .= <$filehandle> until $buffer =~ /(x|y)\n$/;
return $buffer;
};
}
open my $fh, "<", $filename or die;
my $reader = newDataSetReader($fh);
my $nextRow = $reader->();
我更喜欢这个最后的解决方案,但只有从多个文件中读取才有意义。
当您通过子读取时,您可以轻松插入调试挂钩或预过滤数据,例如将行拆分为字段并返回数组而不是单个字符串。