Perl,为特殊变量$ /指定正则表达式

时间:2012-08-23 18:29:27

标签: perl

我有一个包含文字的CSV文件,其中包含新的换行符。例如

1,b,hello
world,x
2,a,hello

mars,y

要一次连续读取所有内容,我想为$ / special变量指定一个正则表达式。关于我如何做到这一点的任何建议?

我的想法是,如果我为我的特殊变量添加类似“(x | y)\ n”的内容,它应该捕获行以x或y结尾的情况以及新行。

由于

3 个答案:

答案 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以一个不变的部分结束。这个子有几种变化:

  1. 从任何文件句柄中读取:

    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);
    
  2. 构造一个执行阅读的匿名子。 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->();
    

    我更喜欢这个最后的解决方案,但只有从多个文件中读取才有意义。

  3. 当您通过子读取时,您可以轻松插入调试挂钩或预过滤数据,例如将行拆分为字段并返回数组而不是单个字符串。