Perl由regexp问题分裂

时间:2015-10-30 12:55:57

标签: regex perl split

我在Perl上编写了一些解析器,这是分裂的问题。这是我的代码:

my $str = 'a,b,"c,d",e';
my @arr = split(/,(?=([^\"]*\"[^\"]*\")*[^\"]*$)/, $str);
# try to split the string by comma delimiter, but only if comma is followed by the even or zero number of quotes 

foreach my $val (@arr) {
    print "$val\n"
}

我期待以下内容:

a
b
"c,d"
e

但这是我真正收到的:

a
b,"c,d"
b
"c,d"
"c,d"

e

我看到我的字符串部分在数组中,它们的索引是0,2,4,6。但是如何在结果数组中避免这些奇数b,"c,d"和其他其他字符串部分?我的正则表达式分隔符中是否有任何错误,或者是否有一些特殊的split选项?

4 个答案:

答案 0 :(得分:4)

您需要使用非捕获组:

my @arr = split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/, $str);
                      ^^

请参阅IDEONE demo

否则,捕获的文本将作为结果数组的一部分输出。

请参阅perldoc reference

  

如果正则表达式具有分组,则生成的列表也包含分组中匹配的子字符串

答案 1 :(得分:4)

绊倒你的是split中的一项功能,如果您正在使用某个群组并且它已设置为捕获,则会返回已捕获的内容。位'同样。

但是,我建议split模块,而不是使用Text::CSV,它已经为您处理了引用:

#!/usr/bin/env perl
use strict;
use warnings;
use Text::CSV;

my $csv    = Text::CSV->new();
my $fields = $csv->getline( \*DATA );

print join "\n", @$fields;

__DATA__
a,b,"c,d",e

打印:

a
b
c,d
e

我的推理相当简单 - 您正在进行引用匹配,并且可能包含带引号/转义引号等内容,这意味着您尝试进行递归解析,是regex根本不适合做的事情。

答案 2 :(得分:2)

如果你没有真正的正则表达式,你可以使用Text::ParseWordsparse_line()

use  Text::ParseWords;

my $str = 'a,b,"c,d",e';

my @arr = parse_line(',', 1, $str);

foreach (@arr)
{
    print "$_\n";
}

输出:

a
b
"c,d"
e

答案 3 :(得分:0)

匹配而不是拆分。

use strict; use warnings;

my $str = 'a,b,"c,d",e';
my @matches = $str =~ /"[^"]*"|[^,]+/g;
foreach my $val (@matches) {
    print "$val\n"
}