【问题标题】:Regex for nested matches嵌套匹配的正则表达式
【发布时间】:2014-05-25 20:19:22
【问题描述】:

考虑字符串

cos(t(2))+t(51)

使用正则表达式,我想匹配cos(t(2))、t(2) 和t(51)。这适合的一般模式旨在类似于

variable or function name + opening_parenthesis + contents + closing_parenthesis,

其中contents 可以是任何具有相同数量的左括号和右括号的表达式。

我使用的是[a-zA-Z]+\([\W\w]*\),它返回cos(t(2)))+t(51),这当然不是我们想要的结果。

关于如何使用正则表达式实现这一点的任何想法?我特别纠结于“开括号和右括号的数量相等”。

【问题讨论】:

  • 简答:正则表达式无法做到这一点。
  • 稍微长一点的答案:如果你想处理任意嵌套,你需要使用专用的解析器。
  • 正则表达式匹配不能用于统计任意数量的匹配表达式(即平衡表达式)。其原因是基于自动机(语言理论),它基本上表明您尝试匹配的语言(即平衡括号)无法匹配,因为它不是“常规”。不过,您可以使用堆栈/解析器。
  • 一些方言(例如 php/pcre)支持能够匹配嵌套括号的递归模式。你的平台是什么?
  • @niels:不知道,但也许this 有帮助。

标签: regex matlab recursion nested


【解决方案1】:

Niels,这是一个有趣且棘手的问题,因为您正在寻找重叠的匹配项。即使使用递归,任务也不是微不足道的。

您询问了any idea how to achieve this with regex,所以听起来即使这在 matlab 中不可用,您也会有兴趣看到一个答案,告诉您如何在正则表达式中做到这一点。

这对我来说很有意义,因为工具经常更改它们使用的正则表达式库。例如 Notepad++,它曾经有残缺的正则表达式,在版本 6 中切换到 PCRE。(碰巧,PCRE 可以使用这个解决方案。)

在 Perl 和 PCRE 中,您可以使用这个简短的正则表达式:

(?=(\b\w+\((?:\d+|(?1))\)))

这将匹配:

cos(t(2))
t(2)
t(51)

例如,在 php 中,您可以使用此代码(请参阅online demo 底部的结果)。

$regex = "~(?=(\b\w+\((?:\d+|(?1))\)))~";
$string = "cos(t(2))+t(51)";
$count = preg_match_all($regex,$string,$matches);
print_r($matches[1]);

它是如何工作的?

  1. 为了允许重叠匹配,我们使用了前瞻。这样,在匹配cos(t(2)) 之后,引擎将不会将自身定位在cos(t(2)) 之后,而是在cos 中的o 之前
  2. 事实上,引擎实际上并不匹配cos(t(2)),而只是将其捕获到组1。它匹配的是at this position in the string, looking ahead, we can see x 的断言。匹配此断言后,它会尝试从字符串中的下一个位置开始再次匹配它。
  3. lookahead 中的表达式(描述我们正在寻找的内容)几乎非常简单:在 (\b\w+\((?:\d+|(?1))\)) 中,\d+ 之后,| 的交替允许我们重复第一个子程序带有(?1),也就是说,我们当前所在的整个表达式。因此,我们不会递归整个正则表达式(包括前瞻),而是递归其子表达式。

【讨论】:

  • 你知道吗,我之前曾经见过只使用正则表达式的递归。 +1 教我一些新东西。
  • @Joeytje50 是的,正则表达式中的递归并不经常出现,但是当您需要它时,它非常简洁。如果您对正则表达式技巧感兴趣,这个技巧适用于许多情况,并且是我的最爱之一:Match (or replace) a pattern except in situations s1, s2, s3 etc
  • 这看起来很有用。 “可悲的是,该技术并不为人所知”这句话可能是每个程序员都以一种或另一种方式经历过的事情(对我来说,这是文件输入<label>s,人们坚持使用hacky编码)。无论如何,这个正则表达式技巧在某些我可能会遇到的情况下可能真的很有用。例如,我一直想知道如何在 wiki 上的正则表达式查找和替换中排除 <nowiki> 或 <!--comments--> 文本,那里没有真正可用的解析器。这个技巧在那里可能真的很有用。
  • @Joeytje50 That trick could be really useful there. 是的,当然。 something every programmer has experienced one way or the other哈,太对了。 :)
  • @zx81。然而,这很有趣,我想知道这是否真的是一个“正则表达式”,因为它不匹配正则语言。答案的道具,我真的很想知道它是如何工作的。
猜你喜欢
  • 1970-01-01
  • 2012-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多