精通正则表达式
1. 正则表达式入门
^
在字符组中,表示的是要匹配一个未列出的字符
而不是不要匹配列出的字符
在字符组里的连字符-
不在字符组的开头,都是用来表示范围的
神奇的转义
转义字符在字符组内无效
要想在复杂性和完整性求得平衡
一个重要的因素是了解待搜索文本
4. 表达式的匹配原理
正则引擎分类
- DFA(符合或不符合POSIX标准的都属此类) (不支持捕获醒括号和回溯)
- 传统型NFA (支持忽略优先量词)
- POSIX NFA
//忽略优先量词是否支持,支付则是传统NFA
if ( 'nfa not'.match(/nfa|nfa not/).length === 1 ) { //只匹配了nfa 没有批核nfa not
console.log('传统NFA')
}else{
var start_time = new Date().getTime(),
end_time;
"==XX=============================".match(/X(.+)+X/);
end_time = new Date().getTime();
if (end_time - start_time > 3000) {
console.log('POSIX NFA');
}else {
console.log('DNFA');
}
}
规则
优先选择最左端的匹配结果
匹配量词是匹配优先的
匹配量词(? * + 以及{min, max})
/^.*([0-9][0-9])/
这个是匹配字符串最后的两位数字
匹配过程是
^.*
匹配整行- ([0-9][0-9])通知
^.*
能否释放出出一些字符出来让我匹配
例如/^.*([0-9][0-9])/
匹配
about 24 characters long
^.*
匹配整行^.*
释放出g, 匹配错误^.*
释放出n, 匹配失败- 如此循环了15次,知道最后释放为4
^.*
继续释放2进行匹配- 匹配成功
先来先服务
'copyright 2003'.match(/^.*([0-9]+)/)
的匹配结果是啥? 只匹配了3 而没有匹配2003
这里是因为匹配量词有两个地方.*
和[0-9]+
匹配过程是
^.*
匹配了整行- '([0-9]+)': 我要匹配1个及其以上个数字
^.*
: 让出了一个3,[(0-9)+]
: 我满足了匹配条件啦,能多给点数字我吗?^.*
: 我在正则的前面, 是先来的, 你能匹配上, 我就不管你拉- 匹配结束
如果想要匹配2003 怎么整? 非贪婪模式啊 猪头 'copyright 2003'.match(/^.*?([0-9]+)/)
表达式主导还是文本主导
NFA引擎: 表达式主导
\to(nite|knight|night)\
匹配文本...tonight...
目标函数找到了to, 尝试匹配nite(尝试匹配n 然后i 然后是t ) 发现不能匹配
2. 然后尝试knight 尝试匹配k 发现不能匹配
然后匹配night
表达式的控制权在不同的元素之间转换的 称为表达式主导(非确定型有枪自动机)
DFA引擎 : 文本主导
\to(nite|knight|night)\
匹配文本...tonight...
- 检查完to, 开始检查n 发现nite和night还可以匹配上,暂时保留。knight已经无法匹配了 踢出局
- 继续检查i 都可以匹配上
- 检查g 把nite踢出局 匹配night
这种以文本为中心的 称为文本主导(确定型有穷自动机)
回溯
回溯的两个要点
1.
如果需要在"进行尝试"和"跳过尝试"之间选择, 对于匹配邮箱量词, 引擎会优先选择"进行尝试", 而对于忽略优先量词, 会选择"跳过尝试"
距离当前最近存储的选择就是当本地失败强制回溯时返回的, 使用的原则是LIFO(后进先出)
5. 正则表达式实用技巧
6. 打造高效正则表达式
参考文章
- 贪婪和非贪婪的选择还有效率: http://blog.csdn.net/lxcnn/article/details/4756030