我已经构建了一个复杂的(对我而言)正则表达式来解析一些文件名,它广泛适用,除了有一些内部括号的情况。
(?'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)_)?
最终更新:我已经决定尝试解析这种愚蠢的格式是不值得的,所以我会放弃对它的支持,并用我的时间做一些更有成效的事情。谢谢大家的帮助,我现在已经看到了光明!
答案 0 :(得分:2)
将嵌套括号与正则表达式匹配为 a)不可能*,或 b)会导致正则表达式无法维护。
如果您只想尝试匹配第一个(
直到最后一个)
(不检查开始和结束括号是否正确匹配),那么只需删除?
在.*?
之后。
*取决于你正在使用的正则表达式。
答案 1 :(得分:2)
使用递归正则表达式:
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测试,似乎给出了预期的结果(只要圆括号内的字符串不包含_
或]
)。