Perl正则表达式存储数组匹配

时间:2014-05-28 19:41:11

标签: regex perl

我有一个文件,每行包含字符串,如下所示

"229269_2,190594_2,94552_2,266076_2,269628_2,165328_2,99319_2,263339_2,263300_2,99315_2,271509_2,2714",A,1 下一行可能看起来像 84545,X,2

我正在尝试在Perl中解析此文本。注意:当行中有多个引号时,引号存在于字符串中,但如果只有item,则不存在引号 我想将每个项目解析成一个数组。我尝试了以下正则表达式

@fields = ($_ =~  /(\d+\_\d+),*/g);

但缺少最后一个2714。如何捕获边缘情况?任何帮助赞赏。提前致谢

2 个答案:

答案 0 :(得分:1)

看起来您有一个CSV文件,因此请使用实际的CSV解析器,例如Text::CSV

解析列后,您可以将第一个字段分隔到数组中:

use strict;
use warnings;

use Text::CSV;

my $csv = Text::CSV->new ( { binary => 1 } )  # should set binary attribute.
    or die "Cannot use CSV: ".Text::CSV->error_diag ();

my $line = qq{"229269_2,190594_2,94552_2,266076_2,269628_2,165328_2,99319_2,263339_2,263300_2,99315_2,271509_2,2714",A,1 the next line could look like 84545,X,2};

if ($csv->parse($line)) {
    my @columns = $csv->fields();
    my @nums = split ',', $columns[0];

    print "@nums\n";
}

输出:

229269_2 190594_2 94552_2 266076_2 269628_2 165328_2 99319_2 263339_2 263300_2 99315_2 271509_2 2714

为什么不是正则表达式?

是的,当然几乎可以使用正则表达式。但您需要了解的是,这会使您的代码非常脆弱且难以维护。

即使你想使用正则表达式,你仍然应该分两步完成。首先分离CSV的初始列,然后处理您担心的特定列。

因为您只是使用第一列,所以可以使用以下代码:

use strict;
use warnings;

my $line = qq{"229269_2,190594_2,94552_2,266076_2,269628_2,165328_2,99319_2,263339_2,263300_2,99315_2,271509_2,2714",A,1 the next line could look like 84545,X,2};

if ($line =~ /^"(.*?)"|^([^,]*)/) {
    my $column0 = $1 // $2;
    my @nums = split ',', $column0;

    print "@nums\n";
}

上述情况恰好与之前的代码完成相同的事情。然而,它有一个很大的缺陷,对于维护程序员而言,这种情况并不那么明显。

每当一个新的编码人员,甚至是你自己在6个月内查看第一组代码时,您的数据格式就非常明显。您正在使用CSV文件,第一列是一个分隔的列表用逗号。第二个代码也可以工作,但是新的维护者必须真正阅读正则表达式,并弄清楚是什么在理解数据的格式,以及代码是否实际上正确地执行了。

无论如何,尽你所能,但我强烈建议你使用实际的CSV Parser来解析csv文件。

答案 1 :(得分:0)

如果您想要的只是最后两个字段......

   my $string = qq("229269_2,190594_2,94552_2,266076_2,269628_2,165328_2,99319_2,263339_2,263300_2,99315_2,271509_2,2714",A,1);
   $string =~ s/"//g;            # delete the quotes
   my @f = split (/,/, $string); # split on the comma
   pop @f; pop @f;               # jettison the last two columns

   # @f contains what you're looking for