通过未注释的逗号分隔成单词,该逗号不在匹配的括号内

时间:2015-07-10 09:54:58

标签: regex perl

考虑以下字符串:

blah, foo(a,b), bar(c,d), yo

我想提取一个字符串列表:

blah
foo(a,b)
bar(c,d)
yo

在我看来,我应该能够在这里使用引用词,但我正在与正则表达式斗争。有人可以帮助我吗?

3 个答案:

答案 0 :(得分:3)

Perl有一点regex recursion,所以你可以找到:

  • blah一样不包含括号(\w+

  • “呼叫”,如\w+\((?R)(, *(?R))*\)

总正则表达式为(\w+(\((?R)(, ?(?R))*\))?)seems to work

答案 1 :(得分:1)

您可以使用以下正则表达式在分割中使用:

\([^()]*\)(*SKIP)(*F)|\s*,\s*

使用\([^()]*\),我们会匹配(,后跟0个或更多字符而不是(),然后跟)。如果找到括号结构,我们将失败与(*SKIP)(*F)匹配,然后我们只匹配用可选空格包围的逗号。

请参阅demo

#!/usr/bin/perl
my $string= "blah, foo(a,b), bar(c,d), yo";
my @string = split /\([^()]*\)(*SKIP)(*F)|\s*,\s*/, $string;

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

要考虑嵌套平衡括号内的逗号,可以使用

my @string = split /\((?>[^()]|(?R))*\)(*SKIP)(*F)|\s*,\s*/, $string;

这是IDEONE demo

使用\((?>[^()]|(?R))*\),我们匹配所有平衡的(),如果找到动词(*SKIP)(*F),则匹配失败,然后我们将逗号与可选的空格匹配(以免手动)稍后修剪字符串。)

对于blah, foo(b, (a,b)), bar(c,d), yo字符串,结果为:

blah
foo(b, (a,b))
bar(c,d)
yo

答案 2 :(得分:1)

Borodin solution提供了question(与此问题类似)。正则表达式的一个小变化将给你欲望输出:(这不适用于嵌套括号)

<div id="e"/>

输出:

use strict;
use warnings;
use 5.010;

my $line = q<blah, foo(a,b), bar(c,d), yo>;

my @words = $line =~ / (?: \([^)]*\) | [^,] )+ /xg;

say for @words;