使用正则表达式来平衡匹配括号
本文关键字:平衡 正则表达式 | 更新日期: 2023-09-27 18:12:30
我正在尝试创建一个.NET RegEx表达式,该表达式将正确平衡我的括号。我有以下正则表达式:
func([a-zA-Z_][a-zA-Z0-9_]*)'(.*')
我尝试匹配的字符串是这样的:
"test -> funcPow((3),2) * (9+1)"
应该发生的是正则表达式应该匹配从funcPow
到第二个右括号的所有内容。它应该在第二个右括号之后停止。相反,它一直匹配到最后一个右括号。正则表达式返回以下内容:
"funcPow((3),2) * (9+1)"
它应该返回以下内容:
"funcPow((3),2)"
任何这方面的帮助将不胜感激。
正则表达式绝对可以进行平衡括号匹配。 这可能很棘手,并且需要一些更高级的正则表达式功能,但并不难。
例:
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);
平衡匹配组具有几个功能,但对于此示例,我们仅使用捕获删除功能。 行(?<-open> ') )
将匹配)
并删除以前的"打开"捕获。
最棘手的台词是(?(open)(?!))
,所以让我解释一下。 (?(open)
是一个条件表达式,仅在存在"开放"捕获时才匹配。 (?!)
是一个总是失败的消极表达。 因此,(?(open)(?!))
说"如果有开放的捕获,那就失败"。
Microsoft的文档也非常有帮助。
使用平衡组,它是:
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>
''( 也许)
,这样'(
和')
就更"明显"。
如果你真的讨厌自己(以及世界/你的共同程序员(使用这些东西,我建议使用RegexOptions.IgnorePatternWhitespace
并在任何地方"洒"空白:-(
正则表达式仅适用于常规语言。这意味着正则表达式可以找到"a和b的任意组合"之类的东西。(ab
或babbabaaa
等(但他们找不到"n a's, one b, n a's"。( a^n b a^n
(正则表达式不能保证第一组 a 与第二组 a 匹配。
因此,它们无法匹配相同数量的左括号和右括号。编写一个一次遍历一个字符的函数很容易。有两个计数器,一个用于打开圆盘,一个用于关闭。遍历字符串时递增指针,如果返回 false opening_paren_count != closing_parent_count
。
func[a-zA-Z0-9_]*'((([^()])|('([^()]*')))*')
你可以使用它,但如果使用的是 .NET,则可能有更好的替代方法。
这部分你已经知道了:
func[a-zA-Z0-9_]*'( --weird part-- ')
--奇怪的部分-部分只是意味着; (
允许任何字符.
,或|
任何部分(.*)
存在多次,只要它想要)*
。 唯一的问题是,你不能匹配任何字符.
,你必须使用[^()]
来排除括号。
(([^()])|('([^()]*')))*