Regex 检查正则表达式是否不明确

Regex 检查正则表达式是否不明确,regex,regular-language,Regex,Regular Language,我想知道是否有一种方法可以自动检查正则表达式的歧义性。如果有一个字符串可以通过正则表达式中的多个方式进行匹配,则正则表达式被认为是不明确的。例如,给定一个正则表达式R=(ab)*(a | b)*,我们可以检测到R是一个不明确的正则表达式,因为有两种方法可以从R中匹配字符串ab 更新 问题是如何检查正则表达式的定义是否不明确。我知道在regex机制的实际实现中,总是有一种方法可以匹配regex,但请以学术的方式阅读和思考这个问题。你忘记了贪婪。通常一个部分获得第一个DIB,因为它是一个贪婪的匹配,

我想知道是否有一种方法可以自动检查正则表达式的歧义性。如果有一个字符串可以通过正则表达式中的多个方式进行匹配,则正则表达式被认为是不明确的。例如,给定一个正则表达式
R=(ab)*(a | b)*
,我们可以检测到
R
是一个不明确的正则表达式,因为有两种方法可以从R中匹配字符串
ab

更新


问题是如何检查正则表达式的定义是否不明确。我知道在regex机制的实际实现中,总是有一种方法可以匹配regex,但请以学术的方式阅读和思考这个问题。

你忘记了贪婪。通常一个部分获得第一个DIB,因为它是一个贪婪的匹配,所以没有歧义

如果你说的是一个神话般的模式匹配引擎,没有像贪婪这样的实际细节;那么答案是可以的

考虑模式的每个元素。并针对每个可能的字符串尝试每个可能的子集。如果有多个子集与同一模式匹配,则存在歧义。优化此过程以缩短无限时间是读者的一项练习。

一个可能的解决方案:

为regexp构造一个NFA。然后分析NFA,从仅由初始状态组成的一组状态开始。然后进行深度或宽度优先遍历,跟踪是否可以处于多个状态。您还需要跟踪所采用的路径,以消除循环

例如,您的
(ab)*(a | b)*
可以用三种状态建模

 |   a   |   b
p| {q,r} |  {r}
q|  {}   |  {p}
r|  {r}  |  {r}
其中p是起始状态,p和r接受


您需要同时考虑两个字母,并继续进行集合{q,r}和{r}。集合{r}只导致{r}给出一个循环,我们可以关闭该路径。集合{q,r},从{q,r}a将我们带到{r},这是一个接受状态,但是由于这个路径不能接受,如果我们从q开始,我们这里只有一条路径,我们可以在确定循环时关闭它。从{q,r}得到一个b将我们带到{p,r}。因为这两个都接受,我们已经确定了一个模糊的位置,我们可以得出结论,regexp是模糊的。

我读了一篇发表在1980年左右的论文,该论文表明正则表达式是否模糊可以在O(n^4)时间内确定。我希望我能给你推荐信,但是 我不再知道参考资料,甚至不知道杂志。 确定正则表达式是否不明确的更昂贵的方法是构造 使用子集构造从正则表达式得到的有限状态机(最坏情况下在时间和空间上为指数)。现在考虑从NFA状态构造的FSM的任何状态X。 对于任意两个nfa状态n1,n2/X,follow(n1)相交follow(n2)则不为空 正则表达式是不明确的。如果FSM的任何状态都不是这样,则
正则表达式不是不明确的。

正则表达式是不明确的当且仅当相应的Glushkov自动机是不确定的。这可以在线性时间内完成。给你。顺便说一句,确定性正则表达式也以一个明确的名称进行了研究。

这与其说是答案,不如说是评论;)r3mus。不,不是!假设两个选项都同样贪婪,那么“ab”将始终与第一个表达式匹配。因此,结果在任何情况下都是可预测的,没有歧义。贪婪性是特定正则表达式引擎的属性,而不是抽象的正则表达式。问题没有具体说明如何解释它;例如,没有任何语言标记。当您无法匹配时,该怎么办?引擎仍然必须尝试所有可能性:。不管怎样,问题中的模式只是一个例子。如果你说由于“贪婪”,模棱两可从来都不是问题,那你就大错特错了。如果可能的话,我通常会尝试让我的模式只以一种方式匹配,当它们不能匹配时,我会很快失败。那么模式
(ab)*(a | b){100}
呢?“贪婪”对你有什么作用?只是出于好奇,你为什么要这么做?嗯,我不清楚我将如何使用它,但我相信会有几个应用程序。我仍在研究这个问题,所以稍后我会给出更详细的答案。自动测试是否需要自己生成目标字符串
ab
,还是会提交?有趣的问题。我认为你应该把问题扩大一点。首先,你应该解释你所说的“模棱两可”是什么意思,因为这可以用多种方式来解释。接下来,您是在谈论学术正则语言,还是现代正则表达式实现?这些都不一样。我知道我的答案不会很有帮助,但是还没有人提到。任何严肃的反应都需要自动机理论或一些严格的数学证明。也许在另一个网站,甚至在stackexchange,你会得到更好的答案。你的问题更多的是关于数学或计算机科学,而不是关于编程。为什么表中的(p,a)单元格中有{q,r}?我想应该是{q}对吧?为什么我们没有$\epsilon$字符呢?在p状态下,您要么在匹配的开始,要么刚刚匹配完
(ab)
的一个实例。在此状态下,当您看到a时,您可以启动一个新的
(ab)
,它将您带到状态q,或者您可以启动一个
(a | b)
,它将您带到状态r。Posix标准regexp没有锚定,因此匹配不需要在字符串的末尾结束,这就是为什么我不包括epsilon。谢谢,我明白你的意思。但我仍然不能把它推广到解决一般问题上。。。