为什么正则表达式不能使用关键字而不是字符?

时间:2009-03-10 10:19:26

标签: regex language-design

好吧,我几乎不了解RegEx的基础知识,但是为什么他们不能设计它来使用关键字(比如SQL)而不是一些神秘的通配符和符号?

是否因为在运行时解释/解析了RegEx而导致性能下降? (未编译)

或者也许是为了写作的速度?考虑到当你学习一些“简单”的字符组合时,输入1个字符而不是关键字会变得更容易吗?

14 个答案:

答案 0 :(得分:34)

你真的想这个吗?

Pattern findGamesPattern = Pattern.With.Literal(@"<div")
    .WhiteSpace.Repeat.ZeroOrMore
    .Literal(@"class=""game""").WhiteSpace.Repeat.ZeroOrMore.Literal(@"id=""")
    .NamedGroup("gameId", Pattern.With.Digit.Repeat.OneOrMore)
    .Literal(@"-game""")
    .NamedGroup("content", Pattern.With.Anything.Repeat.Lazy.ZeroOrMore)
    .Literal(@"<!--gameStatus")
    .WhiteSpace.Repeat.ZeroOrMore.Literal("=").WhiteSpace.Repeat.ZeroOrMore
    .NamedGroup("gameState", Pattern.With.Digit.Repeat.OneOrMore)
    .Literal("-->");

好的,但是it's your funeral,伙计。

在此处下载执行此操作的库:
http://flimflan.com/blog/ReadableRegularExpressions.aspx

答案 1 :(得分:10)

正则表达式具有数学(实际上是语言理论)背景,并且编码有点像数学公式。您可以通过一组规则来定义它们,例如

  • 每个角色都是正则表达式,代表自己
  • 如果ab是正则表达式,那么a?a|bab也是正则表达式
  • ...

使用基于关键字的语言对简单的正则表达式来说是一个很大的负担。大多数情况下,您只需使用简单的文本字符串作为搜索模式:

grep -R 'main' *.c

或者可能是非常简单的模式:

grep -c ':-[)(]' seidl.txt

一旦习惯了正则表达式,这种语法非常清晰和准确。在更复杂的情况下,你可能会使用其他东西,因为很大的正则表达式显然很难阅读。

答案 2 :(得分:8)

Perl 6在正则表达式可读性方面迈出了相当革命性的一步。考虑一下表格的地址: 100 E Main St Springfield MA 01234

这是一个适度可读的Perl 5兼容正则表达式来解析(许多极端情况未处理):

 m/
     ([1-9]\d*)\s+
     ((?:N|S|E|W)\s+)?
     (\w+(?:\s+\w+)*)\s+
     (ave|ln|st|rd)\s+
     ([:alpha:]+(?:\s+[:alpha:]+)*)\s+
     ([A-Z]{2})\s+
     (\d{5}(?:-\d{4})?)
  /ix;

这个Perl 6正则表达式具有相同的行为:

grammar USMailAddress {
     rule  TOP { <addr> <city> <state> <zip> }

     rule  addr { <[1..9]>\d* <direction>?
                  <streetname> <streettype> }
     token direction { N | S | E | W }
     token streetname { \w+ [ \s+ \w+ ]* }
     token streettype {:i ave | ln | rd | st }
     token city { <alpha> [ \s+ <alpha> ]* }
     token state { <[A..Z]>**{2} }
     token zip { \d**{5} [ - \d**{4} ]? }
  }

Perl 6语法是一个类,并且标记都是可调用的方法。像这样使用它:

if $addr ~~ m/^<USMailAddress::TOP>$/ {
     say "$<city>, $<state>";
}

此示例来自talk I presented研讨会的Frozen Perl 2009。 Perl 6的Rakudo实现足够完整,今天这个例子可以正常工作。

答案 3 :(得分:7)

好吧,如果您有关键字,您如何轻松地将它们与实际匹配的文本区分开来?你会如何处理空白?

来源文字 公司:A部门:B

标准正则表达式:

Company:\s+(.+)\s+Dept.:\s+(.+)

甚至:

Company: (.+) Dept. (.+)

关键字正则表达式(真的很难找到一个稻草人......)

"Company:" whitespace.oneplus group(any.oneplus) whitespace.oneplus "Dept.:" whitespace.oneplus group(any.oneplus)

或简化:

"Company:" space group(any.oneplus) space "Dept.:" space group(any.oneplus)

不,这可能不会更好。

答案 4 :(得分:5)

因为它对应于形式语言理论及其数学符号。

答案 5 :(得分:4)

这是Perl的错!......

实际上,更具体地说,正则表达式来自早期的Unix开发,而简洁的语法则更受重视。存储,处理时间,物理终端等都非常有限,与今天不同。

The history of Regular Expressions on Wikipedia解释更多。

有正则表达式的替代方案,但我不确定是否真的有任何问题。

编辑:由John Saunders修正:正则表达式由Unix推广 ,但首先由QED编辑器实现。对早期系统应用相同的设计约束,甚至更多。

答案 6 :(得分:3)

实际上,不,世界并没有从Unix开始。如果您阅读维基百科文章,您会看到

  

在20世纪50年代,数学家Stephen Cole Kleene使用他的数学符号“常规集”来描述这些模型。 SNOBOL语言是模式匹配的早期实现,但与正则表达式不同。 Ken Thompson将Kleene的符号构建到编辑器QED中,作为匹配文本文件中模式的手段。他后来将这个功能添加到了Unix编辑器ed中,最终导致了流行的搜索工具grep使用正则表达式

答案 7 :(得分:2)

这比PERL早得多。 The Wikipedia entry on Regular Expressions将正则表达式的第一个实现归因于UNIX名称的Ken Thompson,他们在QED中实现了它们,然后是ed编辑器。我猜这些命令因性能原因而有短名称,但在客户端之前很多。 Mastering Regular Expressions是一本关于正则表达式的好书,它提供了注释正则表达式(带有/ x标志)的选项,以便于阅读和理解。

答案 8 :(得分:1)

因为正则表达式的想法 - 就像许多来自UNIX的东西 - 是因为它们简洁,有利于简洁性而不是可读性。这实际上是件好事。我最终编写了15行的正则表达式(反对我更好的判断)。如果它有一个冗长的语法,它就不是一个正则表达式,它就是一个程序。

答案 9 :(得分:1)

实际上很容易实现“正则表达”形式的正则表达式 - 请参阅我的回答here。简而言之:编写一些返回正则表达式字符串的函数(并在必要时获取参数)。

答案 10 :(得分:1)

我不认为关键字会带来任何好处。这样的正则表达式很复杂但也非常强大。

我认为更令人困惑的是,每个支持库都发明了自己的语法,而不是使用(或扩展)经典的Perl正则表达式(例如\ 1,$ 1,{1},...用于替换和更多示例)

答案 11 :(得分:1)

我知道它以错误的方式回答你的问题,但是RegExBuddy有一个功能可以用简单的英语解释你的回归。这可能会让学习起来更容易一些。

答案 12 :(得分:1)

如果您使用的语言支持Posix regexes,则可以使用它们。

一个例子:

\d

相同
[:digit:]

括号表示法在匹配时更加清晰。我仍然会学习“神秘的通配符和符号,因为你仍会在其他人的代码中看到它们,并且需要理解它们。

table on regular-expressions.info's page中有更多示例。

答案 13 :(得分:1)

出于某种原因,我之前的回答被删除了。无论如何,我的东西ruby regexp机器符合该法案,http://www.rubyregexp.sf.net。这是我自己的项目,但我认为它应该有用。