【问题标题】:Capture outer paren/bracket groups while ignoring inner paren groups捕获外部括号/括号组,同时忽略内部括号组
【发布时间】:2020-11-17 01:24:10
【问题描述】:

这是我的previous SO question 的排列组合。答案对我来说非常有效,直到我遇到导致问题的边缘情况。我现在需要一个经过调整的正则表达式模式。我曾尝试在Regex Storm 自己解决这个问题,但我对正则表达式的了解还不够先进。

与我之前的帖子(上面链接)的一个变化是,我现在只对匹配以([ 开头的括号分组感兴趣,而不仅仅是(。分组结束保持不变:)

为了完整起见,这里是整个上一个问题,针对新要求进行了修改:

我正在使用 C# 和正则表达式,尝试捕获外部括号组而忽略内部括号组。我有旧版生成的文本文件,其中包含数千个字符串结构,如下所示:

([txtData] of COMPOSITE
(dirty FALSE)
(composite [txtModel])
(view [star3])
(creationIndex 0)
(creationProps )
(instanceNameSpecified FALSE)
(containsObject nil)
(sName txtData)
(txtDynamic FALSE)
(txtSubComposites )
(txtSubObjects )
(txtSubConnections )
)

([txtUI] of COMPOSITE
(dirty FALSE)
(composite [txtModel])
(view [star2])
(creationIndex 0)
(creationProps )
(instanceNameSpecified FALSE)
(containsObject nil)
(sName ApplicationWindow)
(txtDynamic FALSE)
(txtSubComposites )
(txtSubObjects )
(txtSubConnections )
)

([star38] of COMPOSITE
(dirty FALSE)
(composite [txtUI])
(view [star39])
(creationIndex 26)
(creationProps composite [txtUI] sName Bestellblatt)
(instanceNameSpecified TRUE)
(containsObject COMPOSITE)
(sName Bestellblatt)
(txtDynamic FALSE)
(txtSubComposites )
(txtSubObjects )
(txtSubConnections )
)

我正在寻找一个正则表达式来捕获上面示例中的 3 个分组,这是上一个 SO 帖子中的解决方案:

Regex regex = new Regex(@"\((?>\((?<c>)|[^()]+|\)(?<-c>))*(?(c)(?!))\)"); 
return regex.Matches(str);

我需要对上面的正则表达式模式稍作调整,使其只匹配以([ 开头的分组,而不仅仅是(。结局不变:)

需求匹配很简单:

  1. 左括号 + 方括号 (([) 是文件中的第一个字符,或者它跟在 newline 之后。
  2. 右括号是文件中的最后一个字符,或者后面跟一个newline

我希望正则表达式模式忽略所有不遵守上述数字 1 和 2 的括号分组。 “忽略”是指不应将它们视为匹配项 - 但应将它们作为外部分组匹配项的一部分返回。

所以,为了实现我的目标,当我的 C# 正则表达式与上面的示例运行时,我应该返回一个正则表达式 MatchCollection,其中正好有 3 个匹配项,如上所示。

它是怎么做的?

【问题讨论】:

  • Regex.Matches(text, @"(?=\(\[)^\((?&gt;\((?&lt;c&gt;)|[^()]+|\)(?&lt;-c&gt;))*\)\r?$", RegexOptions.Multiline).Cast&lt;Match&gt;().Select(x =&gt; x.Value).ToList()?

标签: c# regex regex-group


【解决方案1】:

您可以在模式的开头应用正向前瞻,这将需要在初始 ( 之后使用 [。此外,由于前导 ([ 只能出现在行首,而结束 ) 只能出现在行尾,因此添加 ^\r?$ 锚点是有意义的(注意 \r?是必需的,因为多行模式下的$ 只匹配\n 之前的位置,而不是\r 之前的位置。

因此,您的正则表达式可能会调整为

var results = Regex.Matches(text, 
                  @"^\((?=\[)(?>\((?<c>)|[^()]+|\)(?<-c>))*\)\r?$", 
                  RegexOptions.Multiline)
              .Cast<Match>()
              .Select(x => x.Value)
              .ToList();

请参阅.NET regex demo

详情

  • ^ - 行首
  • \( - 一个 ( 字符
  • (?=\[) - [ 应该紧跟当前位置
  • (?&gt;\((?&lt;c&gt;)|[^()]+|\)(?&lt;-c&gt;))* - 0 次或多次重复
    • \((?&lt;c&gt;)| - ( 并且一个空值被压入`Group "c" 捕获堆栈,或者
    • [^()]+| - 除() 之外的0 个或多个字符,或
    • \)(?&lt;-c&gt;) - ) 并从 `Group "c" 捕获堆栈中弹出一个空值
  • \) - 一个 ) 字符
  • \r?$ - 可选的 CR 和行尾。

【讨论】:

    猜你喜欢
    • 2017-04-02
    • 2011-05-31
    • 1970-01-01
    • 1970-01-01
    • 2018-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多