正则表达式:使用周围的括号作为分隔符,而忽略任何内部括号

时间:2009-11-18 11:36:45

标签: regex

我已经构建了一个复杂的(对我而言)正则表达式来解析一些文件名,它广泛适用,除了有一些内部括号的情况。

(?'field'F[0-9]{1,4})(?'term'\(.*?\))(?'operator'_(OR|NOT|AND)_)?

在以下示例中,我需要在评论之后获取组,但在第3个示例中,我得到的是((brackets)而不是((brackets)are valid)

对于我的生活,我无法弄清楚如何扩展它以寻找最后的支架。

C:\Temp\[DB_3][DT_2][F30(green)].vsl // F30 (green)
C:\Temp\[DB_3][DT_2][F21(red)_OR_F21(blue)_NOT_F21(pink)].vsl // F21 (red) _OR_ OR
C:\Temp\[DB_3][DT_2][F21((brackets)are valid)].vsl // F21 ((brackets)are valid)
C:\Temp\[DB_3][DT_2][F21(any old brackets)))))are valid)].vsl // F21 (any old brackets)))))are valid)
C:\Temp\[DB_3][DT_2][F21(brackets))))))_OR_F21(blue)].vsl // F21 (brackets)))))) _OR_ OR

由于


更新:我正在使用RegExr进行实验,然后在C#中实现如下:

Regex r = new Regex(pattern, RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace);

foreach(Match m in r.Matches(foo))
{
    //etc
}

更新2:我不需要匹配括号。在一组括号内可以是任何数据,我只需要它用外括号终止。


更新3:

另一种尝试,这可以使用额外的括号(示例3和4),但仍然无法拆分额外的术语(示例5),但不幸的是包括终止]在组中。我怎样才能搜索(但不包括))_)]作为分隔符,但只包括括号?

(?'field'F[0-9]{1,4})(?'term'\(.*?\)[\]])(?'operator'_(OR|NOT|AND)_)?

最终更新:我已经决定尝试解析这种愚蠢的格式是不值得的,所以我会放弃对它的支持,并用我的时间做一些更有成效的事情。谢谢大家的帮助,我现在已经看到了光明!

5 个答案:

答案 0 :(得分:2)

将嵌套括号与正则表达式匹配为 a)不可能*,或 b)会导致正则表达式无法维护。

如果您只想尝试匹配第一个(直到最后一个)(不检查开始和结束括号是否正确匹配),那么只需删除?.*?之后。

*取决于你正在使用的正则表达式。

答案 1 :(得分:2)

嗯,对于大多数正则表达式引擎来说,这通常是不可能的。虽然有可能在perl:

PerlMonks

使用递归正则表达式:

use strict;
use warnings;

my $textInner =
  '(outer(inner(most "this (shouldn\'t match)" inner)))';
my $innerRe;
my $idx=0;
my(@match);

$innerRe = qr/
                \(
                (
                   (?:
                      [^()"]+
                   |
                      "[^"]*"
                   |
                      (??{$innerRe})
                   )*
                )
                \)(?{$match[$idx++]=$1;})
             /sx;

$textInner =~ /^$innerRe/g;

print "inner: $match[0]\n";

也可以在大多数正则表达式引擎中执行此操作,前提是您希望将其固定到支架嵌套的固定深度。我刚才在java中写了一些东西,它会构造一个匹配括号最多6个的正则表达式。

这是我用于生成正则表达式的java函数:

public static String generateParensMatchStr(int depth, char openParen, char closeParen)
{
    if (depth == 0)
        return ".*?";
    else
        return "(?:\\" + openParen + generateParensMatchStr(depth - 1, openParen, closeParen) + "\\" +closeParen + "|.*?)+?";
}

答案 2 :(得分:2)

这是我在python中的另一个测试结果

x="""C:\Temp\[DB_3][DT_2][F30(green)].vsl // F30 (green)
C:\Temp\[DB_3][DT_2][F21(red)_OR_F21(blue)_NOT_F21(pink)].vsl // F21 (red) _OR_ OR
C:\Temp\[DB_3][DT_2][F21((brackets)are valid)].vsl // F21 ((brackets)are valid)
C:\Temp\[DB_3][DT_2][F21(any old brackets)))))are valid)].vsl // F21 (any old brackets)))))are valid)
C:\Temp\[DB_3][DT_2][F21(brackets))))))_OR_F21(blue)].vsl // F21 (brackets)))))) _OR_ OR"""
x=re.sub("//.*","",x)
x=re.sub("(_(OR|NOT|AND)_).*?]"," \\1 \\2]",x)
x=re.findall("(?:F[0-9]{1,4}\(.*\).*(?=]))",x)
for x in x:print x

这给出了

F30(green)
F21(red) _OR_ OR
F21((brackets)are valid)
F21(any old brackets)))))are valid)
F21(brackets)))))) _OR_ OR

这会符合您的预期结果吗?

答案 3 :(得分:1)

re.findall("((?:F[0-9]{1,4}\(.*\))(?:_(?:OR|NOT|AND)_)?)+?",YOURTEXT)

GOTS

['F30(green)', 'F21(red)_OR_F21(blue)_NOT_F21(pink)', 'F21((brackets)are valid)', 'F21(any old brackets)))))are valid)', 'F21(brackets))))))_OR_F21(blue)']

在python中,你怎么看?

答案 4 :(得分:1)

试试这个

/(F[0-9]{1,4})(\([^_\]]+\))(?:_(OR|NOT|AND)_)?/

使用PHP测试,似乎给出了预期的结果(只要圆括号内的字符串不包含_])。