Perl正则表达式捕获非捕获组

时间:2018-05-08 10:12:30

标签: regex perl regex-group

我使用perl来解析CSV文件。我使用正则表达式来解析它而不是任何库。我知道,有CSV解析器库可用,而不仅仅是一个,但我只是决定使用REGEX。

我创建了我认为这是一个相当不错且正常工作的正则表达式。我最初创建了其他应用程序,它们只使用正则表达式来解析文件。我想在这种情况下重复使用它。

我想用perl的美丽把它放在一行:

my $text = '"",hi there,"","2018-04-23,\" 13:14:53",,hostname,mac,"ipaddress",199';

my @data = $text =~ m/(?:^|,)(?:"(|.*?[^\\])"|([^,]*))(?:|$)/g;

然而,当我在单行程中执行perl时,正则表达式捕获甚至非捕获组。

这是一个测试代码:

my $text = '"",hi there,"","2018-04-23,\" 13:14:53",,hostname,mac,"ipaddress",199';

my @data = $text =~ m/(?:^|,)(?:"(|.*?[^\\])"|([^,]*))(?:|$)/g;
foreach (@data) { print "a --${_}--\n"; }

while ($text =~ m/(?:^|,)(?:"(|.*?[^\\])"|([^,]*))(?:|$)/cg) {
    print "b --${1}${2}--\n";
}

“a”转储的结果是:

a ----
a ----
a ----
a --hi there--
a ----
a ----
a --2018-04-23,\" 13:14:53--
a ----
a ----
a ----
a ----
a --hostname--
a ----
a --mac--
a --ipaddress--
a ----
a ----
a --199--

你可以看到额外的空行而不是“b”转储的正确结果:

b ----
b --hi there--
b ----
b --2018-04-23,\" 13:14:53--
b ----
b --hostname--
b --mac--
b --ipaddress--
b --199--

有没有人遇到过这个问题? 感谢您的答案/想法/错误发现。

1 个答案:

答案 0 :(得分:2)

当我发布我的问题时,我意识到问题不是非捕获组,而是实际捕获组,其中只有一组具有值而另一组在当时是空的。

罪魁祸首是正则表达式的这一部分:

(?:"(|.*?[^\\])"|([^,]*))

branch-reset功能替换非捕获组后,一切都很顺利:

(?|"(|.*?[^\\])"|([^,]*))

所以最终正确的单线工作是:

my @data = $text =~ m/(?:^|,)(?|"(|.*?[^\\])"|([^,]*))(?:|$)/g;

希望有人会发现此信息有用。