【问题标题】:Aren't modern regular expression dialects regular?现代正则表达式方言不是正则吗?
【发布时间】:2011-04-19 04:36:34
【问题描述】:

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

现代正则表达式的哪些特征不是正则?示例会很有帮助。

【问题讨论】:

  • 这应该是一个社区维基
  • @webdestroya:我能理解 CW,但为什么不理解呢?
  • @NullUser - 这不是一个非常主观的问题吗?
  • @web 不。常规语言有一个formal definition。这让我们能够客观地回答哪些正则表达式的特性会使正则表达式变得不规则。
  • @NullUser - 我更新了我的评论。

标签: regex regular-language


【解决方案1】:

几个例子:

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

可能还有其他很好的例子 :-) 如果您对外部堆栈的一些实现细节以及正则表达式和平衡分组以及因此比有限自动机更高阶的自动机进一步感兴趣,我曾经写过两篇关于此的短文( http://www.codeproject.com/KB/recipes/Nested_RegEx_explained.aspx 和http://www.codeproject.com/KB/recipes/RegEx_Balanced_Grouping.aspx)。

无论如何——不管是否有限——我相信这些额外的东西给常规语言带来的力量是巨大的 :-)

兄弟。莫腾

【讨论】:

  • 分组和捕获并不是使语言变得不规则的功能——它们所做的只是提供元数据,而不是改变语言的表现力。显然,任何涉及堆栈(如反向引用)的东西都会产生不规则的语言。
【解决方案2】:

确定性或非确定性有限自动机仅识别由正则表达式描述的正则语言。正则表达式的定义很简单。让 S 是一个字母。那么S的空集、空字符串和每个元素都是正则表达式(在S之上)。让 u 和 v 为正则表达式。然后是u 和 v 是 S 上的正则表达式。这个定义很容易扩展到常规语言。没有其他表达式是正则表达式。正如所指出的,一些反向引用就是一个例子。有关正则语言和表达式的 Wikipedia 页面是很好的参考。

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

{ a^ i b^ i : i

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

【讨论】:

  • 从最初的问题来看,我很确定他理解常规语言和非常规语言之间的区别。他的问题是,现代“正则表达式”实现的哪些特征定义了非正则语言,因此无法使用您列出的操作以某种方式表达。
  • 那么,也许我应该更仔细地阅读!无论如何,我认为我没有造成任何伤害。
  • a^i b^i 肯定是非常规的(它是 DCFG),但我们真的可以使用编程语言的“正则表达式”来表达吗?
  • @Nabb /^( |a(?1)b)$/
【解决方案3】:

首先想到的是反向引用:

(\w*)\s\1

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

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


Perl Compatible RegExp (PCRE) 支持的另一个不规则特性是递归模式:

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

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

【讨论】:

  • 一些反向引用可以用常规语言进行。例如(.)x\1 定义了一种常规语言:“axa”、“bxb”等。我相信只有在与 Kleene 闭包结合使用时,反向引用才会使语言变得不规则。
  • 你不需要那里的空间。 (.*)\1 可以。
  • @Nabb: . 匹配的字符范围远大于\w*\s
  • @Nabb 更多的是为了展示真实世界的用法/为了清楚起见。
猜你喜欢
  • 1970-01-01
  • 2013-11-01
  • 2013-11-18
  • 2011-01-31
  • 1970-01-01
  • 2016-03-18
  • 1970-01-01
  • 1970-01-01
  • 2014-06-04
相关资源
最近更新 更多