网站建设与管理实训主要内容,科技打造巅峰华夏从横推鹰酱开始,厦门建站服务,软件工程最好的培训机构一、匹配场景
判断一个句子是不是正规英文句子 text I am a student 一个正常的英文句子如上#xff0c;英文单词 空格隔开
英文单词 多个英文字符 [a-zA-Z]
空格用 \s 表示
那么一个句子就是单词 空格#xff08;一个或者多个#xff0c;最后那个单词…
一、匹配场景
判断一个句子是不是正规英文句子 text I am a student 一个正常的英文句子如上英文单词 空格隔开
英文单词 多个英文字符 [a-zA-Z]
空格用 \s 表示
那么一个句子就是单词 空格一个或者多个最后那个单词是0个可能有多个单词空格 最后一个句号 .
那正则就是 ^([a-zA-Z](\s)*)$ JAVA代码 public static void main(String[] args) {String text I am a good student;String regex ^([a-zA-Z](\\s)*)$;Pattern pattern Pattern.compile(regex);Matcher matcher pattern.matcher(text);System.out.println(matcher.find());System.out.println(matcher.group(0));} 输出结果 true
I am a good student 二、性能测试
regex101: build, test, and debug regexRegular expression tester with syntax highlighting, explanation, cheat sheet for PHP/PCRE, Python, GO, JavaScript, Java, C#/.NET, Rust.https://regex101.com/
句子改成I am a good good student 匹配成功了。39 step耗时0.1ms
但是假如把句子拉长点最后加上一个问号
I am a good good student 83408 step耗时5.4ms
假如把句子再拉长点那么直接就干爆CPU耗时指数增长
为啥会这样呢
三、正则的回溯陷阱
1、了解下NFA与DFA
DFA (Deterministic finite automaton) 确定型有穷自动机NFA (Non-deterministic finite automaton) 非确定型有穷自动机
DFA 遍历text字符串去和Pattern匹配
NFA遍历Pattern去与text匹配
DFA是电动机 和NFA汽油机 都有很长的历史不过正如汽油机一样NFA 的历史更长一些。也有些系统采用了混合引擎它们会根据任务的不同选择合适的引擎甚至对同一表达式中的不同部分采用不同的引擎以求得功能与速度之间的最佳平衡。 ——《精通正则表达式》
绝大多数编程语言都选择的引擎——NFA (非确定型有穷自动机) 引擎 2、NFA的回溯
字符串 abc
表达式a(d|b)c 注意这个位置回退 3、简易例子分析 表达式 ^(a*)$
文本 aaaaaaaaaaaaaaab 走了16w步花了7.3ms 首先 (a*) 已经匹配到 aaaaaaaaaaaaaaa 了 (a*) 也匹配到 aaaaaaaaaaaaaaa 结束符$去匹配的时候发现text不是结束而是一个b那吐出最后的a变成 (aaaaaaaaaaaaaa) a 没匹配上继续吐
a* a*
(aaaaaaaaaaaaa) (aa)a* a* a*
(aaaaaaaaaaaaa) (a)(a)a* a*
(aaaaaaaaaaaa) (aaa)a* a* a*
(aaaaaaaaaaaa) (aa)(a)a* a* a* a*
(aaaaaaaaaaaa) (a)(a)(a)-- 吐到最后
(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)(a)
直接干爆CPU
4、咋优化?
1、对于 ^(a*)$
直接把表达式 ^(a*)$
改成 ^(a*)$
把后面的 号去掉。
直接就是 5 Step0.1ms 2、对于 ^([a-zA-Z](\s)*)$
把后面的 号去掉。就不回溯了
但是匹配不上因为语句有问题就是空格必须存在但是最后的空格不存在 所以改成 ^[a-zA-Z](\s[a-zA-Z])*$
遇到问号也不回溯 去掉问号也匹配上了