使用Perl中的正则表达式解析CSV数据

时间:2013-11-06 16:54:56

标签: regex perl

我有一个CSV文件,其中每行看起来像这样:

509,,SOME VALUE,0,1,1,0.23

我试图查找两位或更多位数的所有数字 可能会或可能不会跟随或以逗号开头 然后使用此Perl代码将它们放入数组中:

my $file ='somefile.csv';

open my $DATA , "<", $file;
$_ = do {local $/; <$DATA>};
my @A = /,?(\d{2,}),?/g;
close $DATA;

正如预期的那样,它匹配上面一行中的第一个逗号分隔值,但是 它也匹配最后一个值23的{​​{1}}部分。由于0.23,我希望这不匹配。

有人可以帮助我使我的正则表达式更具体,所以它不会找到数字 期间之前或之后呢?

1 个答案:

答案 0 :(得分:2)

按常规表达式在程序中做太多事情往往是不明智的。很容易得到令人费解且难以理解的代码,这些代码可以通过标准Perl更简单地实现。

立即将整个文件拖入内存也会使这个问题比它需要的更加尴尬。逐行读取文件通常是最好和最有效的方法。

我建议你写这样的东西。它读取每一行,从末尾修剪换行符,并使用split将其分隔为字段。然后,使用grep过滤掉所有符合您标准的字段 - 两个或更多个十进制数字,并将其推送到数组@numbers

use strict;
use warnings;

my $file ='somefile.csv';

open my $data , '<', $file;
my @numbers;
while (<$data>) {
  chomp;
  push @numbers, grep /^\d{2,}$/, split /,/;
}
close $data;

print "$_\n" for @numbers;

<强>输出

509

如果您坚持遵循当前的计划,那么此替代计划也将有效。但我希望你看到它远不如我的第一个建议那么明确。

use strict;
use warnings;

my $file ='somefile.csv';

my $data = do {
  open my $fh, '<', $file;
  local $/;
  <$fh>;
};

my @numbers = $data =~ /(?:,|^)\K(\d{2,})(?=,|$)/gm;
print "$_\n" for @numbers;