使用正则表达式查找特定段

时间:2017-03-22 08:47:12

标签: regex regex-greedy balanced-groups

我有一个字符串,我想在特定的段中拆分,但由于两次出现相同的模式,我无法匹配字符串的正确段。

我的字符串:

@if(text.text isempty){<customer_comment>@cc{txt_without_comments}cc@</customer_comment>}else{@if(text.answer=='no'){<customer_comment>@{text.text}</customer_comment>}else{<answer>@{text.text}</answer>}endif@}endif@

我需要匹配:@if(text.text isempty){@ cc {txt_without_comments} cc @} else {....} endif @

而不是else块中的嵌套点。

这是我不完整的正则表达式:

(?<match>(?<open>@if\((?<statement>[^)]*)\)\s*{)(?<ifblock>(.+?)(?:}else{)(?<elseblock>.*))(?<-open>)}endif@)

这个正则表达式在ifblock组中过于贪婪,它应该停在第一个} else {pattern。

编辑: 这是我想要产生的确切结果:

match: @if(text.text isempty){<customer_comment>@cc{txt_without_comments}cc@</customer_comment>}else{@if(text.answer=='no'){<customer_comment>@{text.text}</customer_comment>}else{<answer>@{text.text}</answer>}endif@}endif@

statement: text.text isempty

ifblock: <customer_comment>@cc{txt_without_comments}cc@</customer_comment>

elseblock: @if(text.answer=='no'){<customer_comment>@{text.text}</customer_comment>}else{<answer>@{text.text}</answer>}endif@

1 个答案:

答案 0 :(得分:1)

您没有正确使用balancing groups。必须使用平衡组通过捕获将一些值推入堆栈,并使用其他捕获从堆栈中删除,然后需要conditional construct来检查组堆栈是否为空,如果不是,则失败匹配以强制回溯。

因此,如果正则表达式是您匹配这些字符串的唯一方法,请使用以下内容:

(?s)(?<match>@if\((?<statement>[^)]*)\)\s*{\s*(?<ifblock>.*?)\s*}\s*else\s*{\s*(?<elseblock>@if\s*\((?:(?!@if\s*\(|\}\s*endif@).|(?<a>)@if\s*\(|(?<-a>)\}\s*endif@)*(?(a)(?!)))\}\s*endif@)

请参阅regex demo。但是,编写自定义解析器可能会在这里找到更好的方法。

模式详情

  • (?s) - 单线模式(.匹配换行符)
  • (?<match> - 开始外部群组“匹配”
  • @if\( - 文字字符序列@if(
  • (?<statement>[^)]*) - 群组“声明”捕获除)
  • 以外的0 +字符
  • \)\s*{\s* - ),0 +空格,{,0 +空格
  • (?<ifblock>.*?) - 捕获任何0+字符的“ifblock”组,尽可能少地删除第一个字符...
  • \s*}\s*else\s*{\s* - 0 +空格,},0 +空格,else,0 +空格,{,0 +空格
  • (?<elseblock>@if\s*\((?:(?!@if\s*\(|\}\s*endif@).|(?<a>)@if\s*\(|(?<-a>)\}\s*endif@)*(?(a)(?!))) - 群组“elseblock”捕获:
    • @if\s*\( - @if,0 +空格,(
    • (?: - 交替组的开始,重复0次以上
      • (?!@if\s*\(|\}\s*endif@).| - 任何未启动@if,0 +空格,(序列且未启动},0 +空格,endif@序列的字符或...
      • (?<a>)@if\s*\(| - 将“{1}},0 +空格和@if推入堆栈
      • ( - (?<-a>)\}\s*endif@,0 +空格,}从“a”群组中删除
    • endif@ - 交替小组结束
    • )* - 有条件检查(?(a)(?!))if的平衡量是否匹配
  • endif - \}\s*endif@,0 +空格,}
  • endif@ - 外部“匹配”组的结尾。