【问题标题】:Regular Expression get text between braces including other braces正则表达式获取大括号之间的文本,包括其他大括号
【发布时间】:2020-03-30 15:32:00
【问题描述】:

我有一个“主”字符串,例如:

((Gripper|Open==true OR RIT|Turning==false) AND Robot|PosX >=3 OR (Test|Close==false OR (Gripper|Open==false AND RIT|Turning==false)))

我想在最好的情况下得到三个子字符串:

1: (Gripper|Open==true OR RIT|Turning==false)
2: Robot|PosX >=3
3: (Test|Close==false OR (Gripper|Open==false AND RIT|Turning==false))

但是只有两个(大括号 [1,3] 中的那个)也可以,因为它们可以在主字符串中替换,从而得到第 3 个 [2]。 最好借助正则表达式。

所有子字符串作为孩子进入一个类,因此我可以为每个孩子应用正则表达式并获取他们的子字符串。

1: Test|Close==false
2: (Gripper|Open==false AND RIT|Turning==false)

对于第三个孩子(没有大括号的第一个结果将再次是可选的。

我尝试了类似于Regular expression to extract text between braces 的方法并将匹配的位置放入堆栈,但没有达到预期的结果。

到目前为止我发现的最好的正则表达式是

([^()]+(?:[^()]+)+) or
([^()]+(?:)+)

(说真的,正则表达式很强大,但我不知道上述语句的真正作用)这给了我

 1. Gripper|Open == true OR RIT|Turning==false
 2. AND Robot|PosX >=3 OR
 3. Test|Close==false OR
 4. Gripper|Open==false AND RIT|Turning==false

但是,3+4 应该只在一组中

 Test|Close==false OR (Gripper|Open==false AND RIT|Turning==false)

有谁知道如何做到这一点?

【问题讨论】:

  • 逻辑是什么?为什么 3 +4 应该只在一组?

标签: c# regex


【解决方案1】:

您似乎正在寻找平衡括号,其中匹配以 2 个单词除以管道开始,然后是运算符,后跟等号

在 C# 中,您可以匹配 balanced parenthesis 或使用替换匹配不包含它们的模式。

(?:\(\w+\|\w+\s*[<>!=]{1,2}[^()]*(?>[^()]+|(?<o>)\(|(?<-o>)\))*(?(o)(?!)|)\)|\w+\|\w+\s*[<>!=]{1,2}\S+)
  • (?:非捕获组
    • \(\w+\|\w+\s* 匹配 ( 然后 2 个单词由管道和 0+ 个空格字符分隔
    • [&lt;&gt;!=]{1,2}[^()]* 匹配任何运算符并匹配除() 之外的任何字符
    • (?&gt;原子团
      • [^()]+ 匹配除 () 之外的任何字符 1+ 次
      • |或者
      • (?&lt;o&gt;)\(加入堆栈
      • |或者
      • (?&lt;-o&gt;)\)从堆栈中移除
    • )*关闭原子组并重复0+次
    • (?(o)(?!)|)\) Conditional 与捕获组,评估最终子模式
    • |或者
    • \w+\|\w+\s*[&lt;&gt;!=]{1,2}\S+ 匹配由管道和匹配运算符划分的 2 个单词
  • )关闭非捕获组

Regex demo

【讨论】:

  • 哇,令人印象深刻!只有一件事,你不知道:"[+-=]=" 变成 "[!=]{1,2}" (基本上任何 c# 比较运算符)
  • 你知道为什么RegexConditions = new Regex(@"(?:(\w+\s*\|\s*\w+\s*[!=]{1,2} \s*\w+[^()]*(?>[^()]+|(?)(|(?)))*(?(o)(?!)|) )|\w+\s*\|\s*\w+\s*[!=]{1,2}\s*\w+)"); var 匹配 = 条件。匹配(条件);返回matches.Select(m => m.Value).ToList();确实找到 4 个结果,而 REGEX STORM 只找到三个?
  • 实际上,没关系……还有一些可能的空白。新的完整正则表达式是 (?:(\s*\w+\s*\|\s*\w+\s*[!=]{1,2}\s*\w+\s*[^() ]*(?>[^()]+|(?)(|(?)))*(?(o)(?!)|))|\s*\w+\s *\|\s*\w+\s*[!=]{1,2}\s*\w+\s*)
【解决方案2】:

你可以试试:

(?<=\))(?!\()[^()]+|\((?!\()[^)]+\)

Regex101

说明:

(?<=\))(?!\()[^()]+ OR \((?!\()[^)]+\)

“OR”之前的第一部分基本匹配AND Robot|PosX >=3 OR

  1. (?&lt;=\))negative lookbehind:匹配当前字符,如果 前一个字符不是 )
  2. (?!\() 负前瞻:如果是下一个则匹配当前字符 字符不是(或)
  3. [^()]+ 匹配任何既不是(也不是)的东西。

OR 之后的最后一部分匹配以( 开头并以) 结尾的任何内容,同时忽略其中的任何左大括号。

【讨论】:

  • 也可以,但是,我更喜欢另一个答案,因为精确的两个词由“|”分隔不包括 (AND/OR/XOR) 布尔运算符的模式
  • 感谢您的选择,但对于公认的解决方案而言,运营成本/运行时间是其两倍以上
  • 是的,可能是这样,但由于我在初始化时只执行一次,这并不重要。无论如何,谢谢。
猜你喜欢
  • 1970-01-01
  • 2011-01-25
  • 2020-03-14
  • 1970-01-01
  • 2015-05-25
  • 1970-01-01
  • 1970-01-01
  • 2014-07-31
  • 2015-12-30
相关资源
最近更新 更多