【问题标题】:Regex with balancing groups带有平衡组的正则表达式
【发布时间】:2016-12-07 19:32:27
【问题描述】:

我需要编写正则表达式,以特殊符号捕获类型名称的通用参数(也可以是通用的),如下所示:

System.Action[Int32,Dictionary[Int32,Int32],Int32]

假设类型名称为[\w.]+,参数为[\w.,\[\]]+ 所以我只需要抓住Int32Dictionary[Int32,Int32]Int32

如果平衡组堆栈为空,我基本上需要采取一些措施,但我不太明白如何。

UPD

下面的答案帮助我快速解决了问题(但没有适当的验证并且深度限制 = 1),但我已经设法通过组平衡做到了:

^[\w.]+                                              #Type name
\[(?<delim>)                                         #Opening bracet and first delimiter
[\w.]+                                               #Minimal content
(
[\w.]+                                                       
((?(open)|(?<param-delim>)),(?(open)|(?<delim>)))*   #Cutting param if balanced before comma and placing delimiter
((?<open>\[))*                                       #Counting [
((?<-open>\]))*                                      #Counting ]
)*
(?(open)|(?<param-delim>))\]                         #Cutting last param if balanced
(?(open)(?!)                                         #Checking balance
)$

Demo

UPD2(上次优化)

^[\w.]+
\[(?<delim>)
[\w.]+
(?:
 (?:(?(open)|(?<param-delim>)),(?(open)|(?<delim>))[\w.]+)?
 (?:(?<open>\[)[\w.]+)?
 (?:(?<-open>\]))*
)*
(?(open)|(?<param-delim>))\]
(?(open)(?!)
)$

【问题讨论】:

标签: c# .net regex balancing-groups


【解决方案1】:

我建议捕获这些值使用

\w+(?:\.\w+)*\[(?:,?(?<res>\w+(?:\[[^][]*])?))*

请参阅regex demo

详情:

  • \w+(?:\.\w+)* - 匹配 1+ 个单词字符,后跟 . + 1+ 个单词字符 1 次或更多次
  • \[ - 文字 [
  • (?:,?(?&lt;res&gt;\w+(?:\[[^][]*])?))* - 0 个或多个序列:
    • ,? - 可选逗号
    • (?&lt;res&gt;\w+(?:\[[^][]*])?) - 组“res”捕获:
      • \w+ - 一个或多个单词字符(也许,你想要[\w.]+
      • (?:\[[^][]*])? - 1 或 0(将 ? 更改为 * 以匹配 1 或更多)[ 序列,除 [] 之外的 0+ 个字符,以及结束 ]

C# demo below:

var line = "System.Action[Int32,Dictionary[Int32,Int32],Int32]";
var pattern = @"\w+(?:\.\w+)*\[(?:,?(?<res>\w+(?:\[[^][]*])?))*";
var result = Regex.Matches(line, pattern)
        .Cast<Match>()
        .SelectMany(x => x.Groups["res"].Captures.Cast<Capture>()
            .Select(t => t.Value))
        .ToList();
foreach (var s in result) // DEMO
    Console.WriteLine(s);

更新:要考虑未知深度 [...] 子字符串,请使用

\w+(?:\.\w+)*\[(?:\s*,?\s*(?<res>\w+(?:\[(?>[^][]+|(?<o>\[)|(?<-o>]))*(?(o)(?!))])?))*

regex demo

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2013-06-04
  • 2015-11-04
  • 2015-11-13
  • 2019-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-30
相关资源
最近更新 更多