【问题标题】:Getting the outer most delimiters in Regular Expressions获取正则表达式中最外层的分隔符
【发布时间】:2014-04-18 00:49:27
【问题描述】:

有没有办法使用正则表达式来获取最外层分隔符之间的文本?我这里有一个字符串,想在最外面的{%%%%%%} 分隔符之间获取文本:

Hello {%%%=Select(DepartmentID,1,{%%%=if(Gender="M","Mr.","Ms.")%%%}%%%} {%LastName%}

我想得到的文字是:

=Select(DepartmentID,1,{%%%=if(Gender="M","Mr.","Ms.")%%%}

这个正则表达式是什么?我知道里面的文字没有多大意义,这只是一个例子。

【问题讨论】:

  • 为什么不用{%%%(.*)%%%} 而使用$1
  • @EugenRieck 如果有多组分隔符(非嵌套)将失败:{%%%foo%%%} {%%%bar%%%}
  • 如果代码是一个可接受的解决方案,请考虑使用堆栈来跟踪打开和关闭分隔符。
  • @Sam 啊,我现在明白了,OQ 中不排除这种情况。

标签: regex vb.net recursive-regex


【解决方案1】:

这个模式会做一个积极的前瞻:

[^%=]*.{%%%(.+)%%%}.+[^%}]*

捕获组:

$1

示例:http://regex101.com/r/eG4fV9

编辑:似乎有些人喜欢在答案被选为correct 之后加入,然后添加可能不起作用的场景。没关系,但是,根据使用某些东西的情况,可以做出任何东西incorrect

原答案:

(?<={%%%=).+(?=}%%%)[^%]

可选:

[^%=]*.{%%%=(.+)%%%}.+[^%}]*

这将保留匹配中的= 符号。

【讨论】:

  • 这几乎可以工作,但它会将 %%% 留在找到的字符串中
  • 这还是不正确的;结束分隔符是%%%},而不是}%%%。你也需要摆脱[^%]
  • @Chris 鉴于您在问题中设置的要求,您选择的解决方案绝对不正确。例如,这个正则表达式不匹配 {%%%=abcd%%%} 它也不匹配 {%%%=ab{%%%=abcd%%%}cd%%%}。
【解决方案2】:

试试这个:/.*?\{\%\%\%(.*)\%\%\%\}.*/

这是fiddle

【讨论】:

  • JavaScript 正则表达式确实支持贪婪与非贪婪。 .* 匹配将尽可能大 .*? 匹配将尽可能小
【解决方案3】:

一般来说,如果您找不到分隔符的某些独特功能(例如在 cmets 中提到的 Eugen Rieck - 这是一个很好的特定解决方案如果他只将其更改为非贪婪),标准正则表达式做不到。

一些正则表达式引擎,例如 Ruby 的 Oniguruma,可以通过使用递归正则表达式。类似的东西(在我的脑海中):

/{(?<braced>[^{}]*(?:{\g<braced>}[^{}]*)?)}/

Demo

【讨论】:

  • 而原因(据我所知)是因为正则表达式不能真正“计数”。你不得不说,这是第一次打开,第二次打开,第二次关闭,第一次关闭。
  • 贪婪是越过关闭内部分隔符所必需的,但正如@Sam 指出的那样,OQ 中不排除并行构造。
  • @EugenRieck:啊,对。我没有注意到内部的也是 %%% 。所以,是的,你能做到的最好。
【解决方案4】:

克里斯,这里有两个选项符合您的要求,使用递归正则表达式:

选项 1:

\{((?:[^{}]++|(?R))*)\}

选项 2:

\{(([^{}]*+)(?:(?R)(?2))*)\}

这是 PCRE 语法,例如在 PHP 中有效。

您使用什么语言和正则表达式引擎?这些模式可以适应一些其他支持递归的风格。

【讨论】:

  • zx81,我在 VB.net 中使用正则表达式
猜你喜欢
  • 2013-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-06
相关资源
最近更新 更多