正则语言的 并 交 差

请关注我们的技术创业项目 Terark,领先的数据技术提供商


本文转载于我自己的官方网站:nfabo.cn

正则语言的 并 交 差

正则表达式,描述的是正则语言, 学过形式语言与自动机理论的人应该都知道,正则语言在运算下都是封闭的;但是,根据 Wikipedia 的描述,到目前为止,还没有任何一个已知的正则语法(Flavor)将纳入正则语法。理论与实践之间竟然隔着这么巨大的鸿沟!

虽然 Perl 正则中支持的环视(Look Around)在某种意义上可以认为是受限子集,之所以说是受限,因为你无法自由组合并交差操作。另一方面,环视在这些引擎中都是以回溯的方式实现的,效率十分低下。

其实,不光正则语言在运算下都是封闭的,而且,用来表达正则语言的 DFA 可以比较高效地实现这些操作,对比 NFA 转 DFA 的 O(2n),并交差的复杂度是O(n*m),补的复杂度是O(n);这比  O(2n) 要乐观地多,而且,这只是最坏情况下的复杂度,现实中很多时候都是 O(n1+ε),这其中的 ε 往往接近于0,NFA 转 DFA 的最坏 O(2n)在现实中也往往是O(n1+ε),不过这个 ε 往往要大一些。

经过一番努力,我填补了交 、 差这个鸿沟,为了语言的完备性和易用性,同时也实现了传统正则的连接重复,为了区别于传统的 RegEx,暂且把它叫 RegEx++

在语言设计上,一方面为了避免处理无比复杂的转义、字符类、unicode之类的泥潭,另一方面也为了兼容传统的正则,我设计的 RegEx++ 语言分为两部分,一部分是去除了环视和反向引用的Perl正则(re2语法),一部分是 RegEx++ 特有的 、 连接重复

以 BNF 范式表达

Union  :=Inter{'||'Union}
Inter  :=ConCat{'&&'ConCat|'&!'ConCat}
ConCat :=Repeat{Repeat}
Repeat :=Atom['?'|'*'|'+'|Range]
Atom   :='{{'Regex'}}'|'('Union')'
Range  :='{'Min[','Max]|','Max'}'

用更通俗的方式表达

优先级操作符说明
最高{{Plain Old Regex}}{{}}括起来的部分是传统的正则表达式,使用 re2 的 Parser 解析
较高(   )调整优先级
?重复:0次或1次语法和意义与传统正则相同
*重复:0次或多次
+重复:1次或多次
{min,max}重复:最少min次,最多max次
无操作符连接,连着写就行
较低&&交,x && y 表示既能匹配 x 又能匹配 y
&!差,x &! y 表示能匹配 x 但不能匹配 y
最低||并,x || y 表达能匹配 x 或者能匹配 y

这里面唯一比较别扭的是{{ }}括起来的 Plain Old Regex, 值得一提的是,{{ 和 }},用来括住正则表达式(re2语法),一个语法正确并且规范的正则表达式中不会出现 {{ 和 }},只有一个例外:\{{,这个例外很容易处理。其实严格讲,语法正确的正则表达式中可以出现 {{ 和 }},但这样正则表达式往往是有问题的,和 } 用作非元字符时,需要转义(\{\}),而 和 不转义时是元字符,不会出现 {{ 和 }}, Plain Old Regex 允许未转义的 { 和 } 是为了最大限度地“容忍错误”,传统正则语法甚至容忍这样的正则: [[[[]*,还有 ]{{1-2},你知道这都是什么意思吗?

最后

通过 这个测试页面 可以看到一些例子和相应的 DFA/NFA 状态转移图。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值