精通正则表达式读书笔记(二)

DFA VS NFA

DFA:确定有限自动机。对一个输入,只有一个转移状态。

NFA:非确定有限自动机。对一个输入,可以有多个转移状态。


DFA的一个例子:

如果模式串为: abc|abcdef,待匹配串为abcdef,在DFA中,它总是会去尝试所有可能的匹配。

首先它会用abc中的a来匹配,发现满足;同时它还会用abcdef中的a来匹配,发现也满足。这时它会同时保留两个匹配的串。

接着往下匹配bc。

直到字符d。这时左边的abc无法匹配了,因而左边的模式就会被记录为不匹配。而右边的abcdef模式串仍然能够匹配。

这样就会一直用右边的abcdef模式串来匹配剩下的字符。

DFA总是试图去匹配所有的模式,并且通常是一种最长匹配。


而如果用NFA来匹配,这时就往往会采用一种最先匹配策略。

当abc串匹配了abcdef之后,它就认为匹配成功了,就不会再用右边的abcdef来匹配剩下的字符。

以下的python代码可以证实采用了NFA的匹配策略:

import re
p=re.compile(r'(abc)|(abcdef)')
s='abcdef'
m=p.match(s)
print m.groups()
会输出('abc', None)。

DFA的特点:没有回溯,速度非常快。但是不能捕获分组,因而支持的模式复杂度有限。

NFA的特点:功能强大,能支持极其复杂的模式。但是因为有回溯,速度视模式本身而定。不合理的模式会导致大量回溯,从而导致性能低下。

目前大多数正则表达式实现都是NFA,如python, java.util.regex, .NET等。部分古老的实现如awk实用DFA。


匹配优先 VS 忽略优先

匹配优先:*

忽略优先:*?


从路径中获取文件名:

两种路径方式: /usr/bin/gcc或者C:\Windows\Messenger,因此模式会涉及到两种,这里以前者为例。

有两种思路:

1. 从头开始匹配,这种思路本质上是希望将最后一个'/'前的字符全部去掉。用perl可写成如下:

$f =~ s{^.*/}{};

即用^.*/这个模式来匹配包括最后一个/在内的之前所有字符。


2. 从尾开始匹配,这种思路是希望从后往前找,直到碰到/就停止。

这时我们可以用以下的模式来匹配:

[^/]*$,然后使用分组捕获即可。


分析:无论哪一种思路,其实都有一个匹配优先,这就意味着都会有回溯。因而在NFA的情况下性能都不会特别好。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值