- 1. 正则表达式http://www.cnxct.com/CFC4N
- 2. 搜索文件,但只记得其中几个字符
搜索文件,只记得一共有几个字符
当我是个小白
- 3. 使用通配符“*”搜索:*.docData Structures.doc
Database.doc
Databook.doc
Windows.doc正在搜索…
- 4. 使用通配符“?”搜索:Data????.docDatabase.doc
Databook.doc正在搜索…
- 5. *.doc
Data????.doc使用通配符,可以查找符合指定模式的文件名称。
- 6. 长大后运维:处理故障,抽取有固定格式的日志
程序:处理用户输入,是否为合法数据
DBA:模糊查询(REGEXP),偶尔也要处理日志
当你长大后,你发现*、?这些(通配义字符)已经不能满足你的需求了。
- 7. 情景忘记大写还是小写:hi还是Hi[Hh]i(h|H)i搜两遍?试试正则吧
- 8. 最简单的正则表达式表达式:hi能匹配的字符串(举例):hihimhisthisPhilips
- 9. 最简单的正则表达式只想要这个结果:hi改成这个:\bhi\b\b[Hh]i\b\b(H|h)i\b那么只匹配:hi
- 10. 最简单的正则表达式匹配QQ号:\d+匹配结果:10000,1234567,222222,8888888
- 11. 然后呢?\b \w \d () [] \W \s \S ……这些都是什么意思?
(?>) (?<=) (?) \p{Inname}这些又是些什么呢?
\x{4e00}-\x{9fa5} \x80-\xff 这些呢?
- 12. 正则表达式概念 !@#$%^&**&%#@%
元字符:
. 除换行以外的其他任意字符
\s 空白字符
\S 除空白字符以外的任意字符
\w 字母、数字、下划线
\W 除了字母、数字、下划线以外的任意字符
\d 数字 0-9
\D 除了数字之外的任意字符
…… 等等等等
\b 单词边界
^ 字符串的开始
$ 字符串结束
(?=…) 环视(零宽断言) 后面的字符串符合表达式…的时候的位置
(?!)
* 0到无数次
+ 1到无数次
? 0 或者1 次
{n} 重复N次
{n,} 重复至少N次
{n,m} n到m次
[] 字符组,字符范围
() 捕获组(子表达式)
…… 等等
- 13. 正则表达式字符组:
[0-9] 数字0到数组9之间的任意一个
[a-z] 字母a到字母z的任意一个
[^cfC] 除了字母 c f C的任意一个字符
[\u4e00-\u9fa5] 汉字中的任意一个汉字 注
[^a-z] 除了字母 a 到字母z的任意一个字符
[^-a-c] 除了 - 字符以及字母a到字母z的任意一个字符
| 多选分支,或者关系
\1 \2 … 反向引用 < (\w) >.*\1> 引用第一个捕获组的结果,用于匹配html的闭合标签表达式 [^Win] ,匹配字符串Windows 的结果是什么呢?
表达式 ab|cd ,能匹配aabd 吗?aacd呢?
- 14. “^”和“$”表达式:^hi能匹配:hihimhidden“^”代表字符串的开头“$”代表字符串的结束表达式:hi$能匹配:hichiOrochi
- 15. “^”和“$”表达式^hi$只能匹配hi“^”代表字符串的开头“$”代表字符串的结束
- 16. “[ ]”方括号“[ ]”匹配指定一堆字符中的一个。表达式:^[a-z]at$能匹配的字符串(举例):catmatzat
- 17. “[ ]”方括号“[ ]”匹配指定一堆字符中的一个。表达式:^[A-Za-z]at$能匹配的字符串(举例):CatcatMat
- 18. “[ ]”方括号“[ ]”匹配指定一堆字符中的一个。表达式:^[aeiou]at$能匹配的字符串(举例):aateatiat
- 19. 重复符号“+”“+”表示前一字符模式可以被重复1次或n次。表达式:^go+gle$能匹配的字符串(举例):goglegooglegooooooooooogle
- 20. 重复符号“+”“+”表示前一字符模式可以被重复1次或n次。表达式:^g[aeiou]+gle$能匹配的字符串(举例):gaglegeglegeaglegeaeeaioueagle
- 21. 重复符号“*”“*”表示前一字符模式可以被重复0次或n次。表达式:^go*gle$能匹配的字符串(举例):gglegooglegooooooooooogle
- 22. 重复符号“{x,y}”“{x,y}”表示前一字符模式可以被重复x到y次。表达式:^go{2,4}gle$能匹配的字符串(仅3个):goooglegooooglegoogle
- 23. 重复符号“{x,}”“{x,}”表示前一字符模式可以被重复至少x次。表达式:^go{2,}gle$能匹配的字符串(举例):goooglegooooglegooglegoooooooooooogle
- 24. 子表达式“( )”“( )”可以指定一堆字符来匹配一个模式。表达式:^(very )*large$能匹配的字符串(举例):very largevery very largelargevery very very very large
- 25. 分支“|”分支“|”用来指定几个规则只要匹配一个规则即成匹配。表达式:^com$|^org$|^net$能匹配的字符串(仅3个):comorgnet
- 26. 分支“|”分支“|”用来指定几个规则只要匹配一个规则即成匹配。表达式:^abc.(com|org|net)$能匹配的字符串(仅3个):abc.comabc.orgabc.net
- 27. 转义符号“\”如果要匹配“[”“^”“+”“)”等等有特殊含义的字符,可以用“\”做转义。表达式:^1\*\(2\+3\)=6$能匹配的字符串(仅1个):1*(2+3)=6
- 28. 小试身手匹配带区号、横杠的电话号码
匹配第一位可能带0的那种手机号码
匹配IP
匹配日期(1-31号)
PHP的面试题 表达式phper(.+), 字符串是phper001,phper002,phper003,那么捕获结果的1组里是什么?
- 29. Q&A结束刚刚开始…
- 30. 正则起源与流派1940 神经学家研究出一种模型,认为神经系统在神经元层面上就是这样工作的。N年后数学家描述《正则集合(regular sets)》
1968年Ken Thompson的文章《regualr....》描述一种正则表达式编译器,该编译器生成IBM 7094的OBJECT代码,也诞生了他的qed,也就是后来的UNIX中ed编辑器的基础
ed没qed先进,他有个命令是这样 g/Regular Expresion/p 成为独立的工具grep(以及拓展的egrep)
- 31. 两种不同引擎qed-->erep-->Egrep
awk\lex sed
POSIX
Perl正则的起源与流派DFA Deterministic finite automaton 确定型有穷自动机
NFA Non-deterministic finite automaton 非确定型有穷自动机Traditional NFA
POSIX NFA引擎类型程序DFAAwk(多数版本)、egrep(多数版本)、flex、lex、Mysql传统NFAGUN Emacs、JAVA、GREP(多数版本)、less、more、PREL、PHP(3套)、Python、ruby、sed(多数版本)、viPOSIX NFADFA/NFA混合Gun awk、gun grep/egrep
- 32. DFA与NFA的区别DFA引擎因为不需要回溯,所以匹配快速,但不支持捕获组,所以也就不支持反向引用和$number这种引用方式,目前使用DFA引擎的语言和工具主要有awk、egrep 和 lex。
POSIX NFA主要指符合POSIX标准的NFA引擎,它的特点主要是提供longest-leftmost匹配,也就是在找到最左侧最长匹配之前,它将继续回溯。同DFA一样,非贪婪模式或者说忽略优先量词对于POSIX NFA同样是没有意义的。
大多数语言和工具使用的是传统型的NFA引擎,它有一些DFA不支持的特性:
捕获组、反向引用和$number引用方式;
环视(Lookaround,(?<=…)、(?…)。
本次分享只讨论标准NFA引擎
- 33. 匹配基础规则有限选择最左端匹配结果
标准量词优先匹配
- 34. 为啥要了解“这么深入”?网页小偷程序(100k内容 PHP就超时)
url 重写 (apache nginx对url处理了2ms)
日志分析 (1G日志处理了1天)
想自己写个像python、php一样的语言
想开发自己的DB,想知道DB语法分析器执行原理
本来就是个爱钻研的人
遇到以上情况,或者符合其中一条的,请继续
- 35. 字符串组成cf位置0位置1位置2字符1字符0
- 36. 占有字符与零宽度正则表达式匹配过程中,如果子表达式匹配到的是字符内容,而非位置,并被保存到最终的匹配结果中,那么就认为这个子表达式是占有字符的;如果子表达式匹配的仅仅是位置,或者匹配的内容并不保存到最终的匹配结果中,那么就认为这个子表达式是零宽度的。
占有字符是互斥的,零宽度是非互斥的。也就是一个字符,同一时间只能由一个子表达式匹配,而一个位置,却可以同时由多个零宽度的子表达式匹配。
- 37. 控制权和传动 正则的匹配过程,通常情况下都是由一个子表达式(可能为一个普通字符、元字符或元字符序列组成)取得控制权,从字符串的某一位置开始尝试匹配,一个子表达式开始尝试匹配的位置,是从前一子表达匹配成功的结束位置开始的。如正则表达式:
(子表达式一)(子表达式二)
假设(子表达式一)为零宽度表达式,由于它匹配开始和结束的位置是同一个,如位置0,那么(子表达式二)是从位置0开始尝试匹配的。
假设(子表达式一)为占有字符的表达式,由于它匹配开始和结束的位置不是同一个,如匹配成功开始于位置0,结束于位置2,那么(子表达式二)是从位置2开始尝试匹配的。
而对于整个表达式来说,通常是由字符串位置0开始尝试匹配的。如果在位置0开始的尝试,匹配到字符串某一位置时整个表达式匹配失败,那么引擎会使正则向前传动,整个表达式从位置1开始重新尝试匹配,依此类推,直到报告匹配成功或尝试到最后一个位置后报告匹配失败。
- 38. 简单的匹配过程源字符串:abc
正则表达式:abc
匹配过程:
首先由字符“a”取得控制权,从位置0开始匹配,由“a”来匹配“a”,匹配成功,控制权交给字符“b”;由于“a”已被“a”匹配,所以“b”从位置1开始尝试匹配,由“b”来匹配“b”,匹配成功,控制权交给“c”;由“c”来匹配“c”,匹配成功。
此时正则表达式匹配完成,报告匹配成功。匹配结果为“abc”,开始位置为0,结束位置为3。
- 39. 含有匹配优先量词的匹配过程(成功)源字符串:abc 正则表达式:ab?c
量词“?”属于匹配优先量词,在可匹配可不匹配时,会先选择尝试匹配,只有这种选择会使整个表达式无法匹配成功时,才会尝试让出匹配到的内容。这里的量词“?”是用来修饰字符“b”的,所以“b?”是一个整体。
匹配过程:
首先由字符“a”取得控制权,从位置0开始匹配,由“a”来匹配“a”,匹配成功,控制权交给字符“b?”;由于“?”是匹配优先量词,所以会先尝试进行匹配,由“b?”来匹配“b”,匹配成功,控制权交给“c”,同时记录一个备选状态;由“c”来匹配“c”,匹配成功。记录的备选状态丢弃。
此时正则表达式匹配完成,报告匹配成功。匹配结果为“abc”,开始位置为0,结束位置为3。
- 40. 零宽度匹配过程源字符串:a12 正则表达式:^(?=[a-z])[a-z0-9]+$
元字符“^”和“$”匹配的只是位置,顺序环视“(?=[a-z])”只进行匹配,并不占有字符,也不将匹配的内容保存到最终的匹配结果,所以都是零宽度的。这个正则的意义就是匹配由字母或数字组成的,第一个字符是字母的字符串。
- 41. 匹配过程: 首先由元字符“^”取得控制权,从位置0开始匹配,“^”匹配的就是开始位置“位置0”,匹配成功,控制权交给顺序环视“(?=[a-z])”
“(?=[a-z])”要求它所在位置右侧必须是字母才能匹配成功,零宽度的子表达式之间是不互斥的,即同一个位置可以同时由多个零宽度子表达式匹配,所以它也是从位置0尝试进行匹配,位置0的右侧是字符“a”,符合要求,匹配成功,控制权交给“[a-z0-9]+”;
因为“(?=[a-z])”只进行匹配,并不将匹配到的内容保存到最后结果,并且“(?=[a-z])”匹配成功的位置是位置0,所以“[a-z0-9]+”也是从位置0开始尝试匹配的,“[a-z0-9]+”首先尝试匹配“a”,匹配成功,继续尝试匹配,可以成功匹配接下来的“1”和“2”,此时已经匹配到位置3,位置3的右侧已没有字符,这时会把控制权交给“$”;
元字符“$”从位置3开始尝试匹配,它匹配的是结束位置,也就是“位置3”,匹配成功。
此时正则表达式匹配完成,报告匹配成功。匹配结果为“a12”,开始位置为0,结束位置为3。其中“^”匹配位置0,“(?=[a-z])”匹配位置0,“[a-z0-9]+”匹配字符串“a12”,“$”匹配位置3。
- 42. 匹配优先表达式:
.+
字符串:testtest
testtest
匹配过程是什么?
如果是.+?
呢?
如何选择使用量词优先,还是忽略优先量词?还是占有优先量词?(.++
) - 43. 茅塞顿开PHP的面试题 表达式phper(.+), 字符串是phper001,phper002,phper003,那么捕获结果的1组里是什么?现在知道了吗?为什么是这个结果?
- 44. 回溯备份状态
当正则遇到优先量词时,遇到“?”,会先记录备份状态,当下一个匹配失败的时候,回到这里,再进行匹配。
字符串:
test1
xxxxx…xxxx
test
(星号处是10W个字符)
表达式:
.+?
(想要的结果是每个闭合的div为一组)分析一下引擎会记录多少个备选状态?
第一个备选状态是几个字符?
第二个呢?
第3 4 5个呢?
第n个呢?
一共多少个字符呢?占多大内存?
- 45. 一个例子DB中有个字段使用了浮点数,需要程序处理。需求是保留小数点后面3位,如果最后一位是0,则保留两位。
字符例子:15.214123、37.500232、154.356
目的: 15.214 37.50
表达式:?
(\.\d\d[1-9]?)\d*$1\d*改成\d+ (\.\d\d[1-9]?) \d+ $1
- 46. 占有优先量词与固化分组*+、++、?+
匹配过程如何?
上个例子如何解决?
\.(\d\d(?>[1-9]?))\d+
- 47. 捕获组与反向引用捕获组 ()
()是子表达式的标识,同时,匹配结果会保存起来,最后一同给出。在表达式中可以直接引用。
比如表达式
用来匹配字符串
和,结果中\1分别是’和”
彪悍的例子
表达式:
([a-z0-9])+
字符串:……
1W个字符
引擎会捕获多少个组呢?
捕获不分组 (?:) - 48. 其他递归
条件判断
字符编码
语言特性
修饰符
NFA表达式主导、DFA文字主导
没想起来的。。。
- 49. 精确高效QQ号的匹配 \d+
IP的匹配 \d+\. \d+\. \d+\. \d+
日期匹配 \d\d
如何改进?误匹配
漏匹配
- 50. 语言特性PHP\PYTHON的环视不支持不确定长度
(?=[0-9]+),.NET支持。
JAVASCRIPT连环视都不支持
- 51. 先粗后细,先加后减 使用正则表达式语法对于目标文本进行描述和界定,可以像画素描一样,先大致勾勒出框架,再逐步在局步实现细节。仍举刚才的手机号的例子,先界定\d{11},总不会错;再细化为1[358]\d{9},就向前迈了一大步(至于第二位是不是3、5、8,这里无意深究,只举这样一个例子,说明逐步细化的过程)。这样做的目的是先消除漏匹配(刚开始先尽可能多地匹配,做加法),然后再一点一点地消除误匹配(做减法)。这样有先有后,在考虑时才不易出错,从而向“不误不漏”这个目标迈进。
- 52. 明确需求 具体说来,就是谨慎用点号这样的元字符,尽可能不用星号和加号这样的任意量词。只要能确定范围的,例如\w,就不要用点号;只要能够预测重复次数的,就不要用任意量词。例如,写析取twitter消息的脚本,假设一条消息的xml正文部分结构是…且正文中无尖括号,那么[^<]{1,480}这种写法的思路要好于.*
原因有二:
一是使用[^<],它保证了文本的范围不会超出下一个小于号所在的位置;
二是明确长度范围,{1,480},其依据是一条twitter消息大致能的字符长度范围。当然,480这个长度是否正确还可推敲,但是这种思路是值得借鉴的。
说得狠一点,“滥用点号、星号和加号甚至括号是不环保、不负责任的做法”。
- 53. 不要让稻草压死骆驼每使用一个普通括号()而不是非捕获型括号(?:…),就会保留一部分内存等着你再次访问。这样的正则表达式、无限次地运行次数,无异于一根根稻草的堆加,终于能将骆驼压死。养成合理使用(?:…)括号的习惯。曾经一个表达式:
([a-z0-9])+
- 54. 少用多选分支c[af]t 与c(a|b|c|d|e|f)t
6次回溯(回溯的主要原因)
适当使用边界字符\bthe\b 匹配 the 不匹配 there^ $ 等分支顺序可以选择字符串中最常出现的字符串放到分支最前面
- 55. 系统内部的优化字符串连接
[abc]当作一个元素,避免三次迭代
化简量词优化
.*跟(?:.)*匹配结果一致,但前效率更高
消除不必要括号
如上,它会用前者代替后者
消除不必要的字符组
[.]中就一个字符,会被优化为\.
过度回溯检测
前面提到过PHP限制回溯次数的截图默认10W次
量词等价转换
\d\d\d\d 跟\d{4}哪个效率高?前者4个元素,后者一个元素
- 56. 正则应用原理表达式编译
检查语法,并编译为内部形式
传动开始
定位至字符串起始位置
元素检测
相连元素、量词修饰符、控制权
寻找匹配结果
NFA找到后锁定,返回。DFA继续下一个,找最长结果
传动装置的驱动过程
没匹配成功,从下一个字符开始
匹配彻底失败
所有字符尝试完毕,返回彻底失败
- 57. 小试身手抓取php.ini中所有配置参数
参考答案:http://www.cnxct.com/cfc4n%E5%B0%8F%E8%AF%95%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/
检测PHP代码中危险函数指令(扫描webshell)
参考答案:http://www.cnxct.com/%E5%A6%82%E4%BD%95%E7%B2%BE%E7%A1%AE%E6%9F%A5%E6%89%BEphp-webshell%E6%9C%A8%E9%A9%AC%EF%BC%9F/
抓取页面所有a标签中链接地址(不符合W3C标准)
写一款SQL语法分析器,拦截危险SQL
- 58. 高手的境界心中无引擎,眼里无流派
- 59. 工具工具地址:http://www.cnxct.com/%E5%A5%BD%E4%B8%9C%E8%A5%BF%E5%85%B1%E4%BA%AB%E5%87%BA%E6%9D%A5-jgsoft-regexbuddy-v310-%E9%9B%B6%E5%94%AE%E7%89%88-%E7%A0%B4%E8%A7%A3%E7%89%88/
- 60. Q&A完参考资料:
CNXCT:http://www.cnxct.com/ (我自己)
雁过无痕:http://blog.csdn.net/lxcnn
我爱正则表达式:http://iregex.org
Benz Bus: http://bencz.blogbus.com (PPT模版背景作者)