现代正则表达方言不规律吗?

时间:2010-09-30 05:55:19

标签: regex regular-language

我在这里看到一些评论,提到现代正则表达式超出了常规语言的表达范围。这是怎么回事?

现代正则表达式的哪些特征不规律?例子很有用。

3 个答案:

答案 0 :(得分:18)

首先想到的是反向引用:

(\w*)\s\1

(匹配一组单词字符,后跟空格字符,然后是之前匹配的同一组)例如:hello hello匹配,hello world不匹配。

此构造不是常规的(即:不能由regular grammar生成)。


Perl兼容RegExp(PCRE)支持的另一个非常规的功能是递归模式:

\((a*|(?R))*\)

这可用于匹配平衡括号和“a”的任意组合(来自wikipedia

答案 1 :(得分:4)

几个例子:

  • 正则表达式支持分组。例如。在Ruby中:/my (group)/.match("my group")[1]将输出“group”。将某些东西存储在一个组中需要一个外部存储器,有限的自动机没有这个存储器。
  • 许多语言,例如C#支持捕获,即每个匹配将在堆栈上捕获 - 例如模式(?<MYGROUP>.)*可以执行多次捕获“。”在同一组。
  • 如上面的用户NullUserException所指出的,分组用于反向引用。反向引用需要一个或多个具有下推自动机功能的外部堆栈(您必须能够在堆栈上推送某些东西并在之后查看或弹出它。
  • 某些引擎可以单独推送和弹出外部堆栈并检查堆栈是否为空。在.NET中,实际上(?<MYGROUP>test)推送堆栈,而(?<-MYGROUP>)弹出堆栈。
  • 像.NET引擎这样的引擎具有平衡的分组概念 - 可以同时推送和弹出外部堆栈。平衡分组语法为(?<FIRSTGROUP-LASTGROUP>),它弹出LASTGROUP并推送自FIRSTGROUP堆栈上的LASTGROUP索引以来的捕获。这实际上可以用来匹配无限嵌套的结构,这绝对超出了有限自动机的能力。

可能存在其他好的例子:-)如果你进一步关注外部堆栈的一些实现细节结合Regex和平衡分组,因此比有限自动机更高阶自动机,我曾经写过两篇关于此的短篇文章( http://www.codeproject.com/KB/recipes/Nested_RegEx_explained.aspx和http://www.codeproject.com/KB/recipes/RegEx_Balanced_Grouping.aspx)。

无论如何 - 有没有 - 我觉得这些额外的东西给普通语言带来的力量很大: - )

溴。的Morten

答案 2 :(得分:3)

确定性或非确定性有限自动机仅识别正则语言,正则语言由正则表达式描述。正则表达式的定义很简单。让 S 为字母表。然后空集,空字符串和 S 的每个元素都是正则表达式(在 S 上)。让 u v 成为正则表达式。然后联合( u | v ),连接( uv )和<(em> u *)< em> u 和 v S 上的正则表达式。该定义很容易扩展到常规语言。没有其他表达式是正则表达式。正如所指出的,一些反向引用就是一个例子。关于常规语言和表达的维基百科页面是很好的参考。

实质上,某些“正则表达式”不是常规的,因为不能构造特定类型的自动机来识别它们。例如,语言

{a ^ i b ^ i i &lt; = 0}

不规律。这是因为接受自动机需要无限多个状态,但接受常规语言的自动机必须具有有限数量的状态。