使用RegEx来平衡匹配括号
我正在尝试创build一个.NET正则expression式,将正确地平衡我的括号。 我有以下正则expression式:
func([a-zA-Z_][a-zA-Z0-9_]*)\(.*\)
我想匹配的string是这样的:
"test -> funcPow((3),2) * (9+1)"
正则expression式应该匹配从funcPow
到第二个funcPow
括号的所有内容。 它应该在第二个右括号之后停止。 相反,它一直匹配到最后一个右括号。 RegEx正在返回这个:
"funcPow((3),2) * (9+1)"
它应该返回这个:
"funcPow((3),2)"
任何帮助,将不胜感激。
正则expression式绝对可以做平衡的括号匹配。 这可能会非常棘手,需要一些更高级的正则expression式function,但这并不难。
例:
var r = new Regex(@" func([a-zA-Z_][a-zA-Z0-9_]*) # The func name \( # First '(' (?: [^()] # Match all non-braces | (?<open> \( ) # Match '(', and capture into 'open' | (?<-open> \) ) # Match ')', and delete the 'open' capture )+ (?(open)(?!)) # Fails if 'open' stack isn't empty! \) # Last ')' ", RegexOptions.IgnorePatternWhitespace);
平衡的匹配组有两个function,但在这个例子中,我们只使用了捕获删除function。 行(?<-open> \) )
将匹配a )
并删除先前的“打开”捕获。
最棘手的一行是(?(open)(?!))
,所以让我解释一下。 (?(open)
是一个条件expression式,只有在“open”捕获的情况下才匹配。 (?(open)(?!))
是一个总是失败的负expression式。因此(?(open)(?!))
表示“一个公开的捕捉,然后失败“。
微软的文档也很有帮助。
使用平衡组,它是:
Regex rx = new Regex(@"func([a-zA-Z_][a-zA-Z0-9_]*)\(((?<BR>\()|(?<-BR>\))|[^()]*)+\)"); var match = rx.Match("funcPow((3),2) * (9+1)"); var str = match.Value; // funcPow((3),2)
(?<BR>\()|(?<-BR>\))
是一个平衡组 (我使用的BR
的名字是Brackets
)。 这样可以更清楚地说明(?<BR>
\( )|(?<-BR>
\) )
,这样\(
和\)
更“明显”。
如果你真的恨自己(和世界/你的同事共同程序员)足够使用这些东西,我build议使用RegexOptions.IgnorePatternWhitespace
和“洒”空白无处不在:-)
正则expression式仅适用于正规语言 。 这意味着一个正则expression式可以find“a和b的任意组合”types的东西( ab
或babbabaaa
等),但是他们找不到“ n a's,one b, n a's”( a^nba^n
)正则expression式不能保证第一组a与第二组a相匹配。
因此,它们不能匹配相等数量的开合括号。 编写一次遍历string一个字符的函数将是很容易的。 有两个柜台,一个开放paren,一个closures。 在遍历string时增加指针,如果opening_paren_count != closing_parent_count
返回false。
func[a-zA-Z0-9_]*\((([^()])|(\([^()]*\)))*\)
你可以使用它,但是如果你使用.NET,可能会有更好的select。
这部分你已经知道:
func[a-zA-Z0-9_]*\( --weird part-- \)
– 简单的部分 – 部分只是意味着; (
允许任何字符,或任何部分(.*)
存在尽可能多的次数)*
。 唯一的问题是,你不能匹配任何字符.
,你必须使用[^()]
来排除括号。
(([^()])|(\([^()]*\)))*