使用正则表达式来平衡匹配括号

本文关键字:平衡 正则表达式 | 更新日期: 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的任意组合"之类的东西。(abbabbabaaa等(但他们找不到"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-- ')
--

奇怪的部分-部分只是意味着; (允许任何字符.,或|任何部分(.*)存在多次,只要它想要)*。 唯一的问题是,你不能匹配任何字符.,你必须使用[^()]来排除括号。

(([^()])|('([^()]*')))*