正则指引

44
正则指引 RegExp Guide shengxuanwei 2014-02-20

Upload: jiyee-sheng

Post on 19-Jul-2015

121 views

Category:

Software


13 download

TRANSCRIPT

Page 1: 正则指引

正则指引 RegExp Guide

shengxuanwei 2014-02-20

Page 2: 正则指引

什么是正则?

• 正则表达式是⼀一种描述字符串结构模式的形式化表达⽅方法

• 使⽤用正则表达式,将会以⼀一个全新的⾓角度看待⽂文本,它们已经不仅仅是⼀一串字符流,⽽而且拥有⼀一定的结构,可以对其进⾏行分解、提取和加⼯工(验证,查找,替换)

Page 3: 正则指引

学习曲线(堪⽐比vi)

• Some people, when confronted with a problem, think,“I know, I'll use regular expressions.” Now they have two problems.

Page 4: 正则指引

正则是什么?• 唬⼈人的正则

• 合法的IP地址

(?s)/\*(?:(?!\*/)[*$ _/+\\-])*(.*?)[*$ _/+\\-]*?\*/

((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?

Page 5: 正则指引

怎么学习正则?• ⽂文本,观察⽂文本,描述⽂文本特征和边界条件

• 语法,学习正则模式,多尝试,多练习

• 基础特性(30min掌握)

• ⾼高级特性(30min了解)

• 原理,学习匹配原理,提⾼高匹配效率

Page 6: 正则指引

《精通正则表达式》

• 权威经典

• ⽆无出其右

Page 7: 正则指引

元字符(meta-characters)

• 特殊字符,提供了强⼤大的描述能⼒力

• 与之相对应的是⽂文字(literal)

. 匹配除换⾏行符以外的任意字符\w 匹配字⺟母或数字或下划线或汉字\s 匹配任意的空⽩白符\d 匹配数字\b 匹配单词的开始或结束^ 匹配字符串的开始$ 匹配字符串的结束

Page 8: 正则指引

字符转义(escape)

• 转义符 \!

• 取消字符的特殊意义

• 例如,\. 匹配字符 .

Page 9: 正则指引

重复量词(Quantifiers)

• 限定了所作⽤用元素的匹配次数

* 重复零次或更多次,等效于{0,}

+ 重复⼀一次或更多次,等效于{1,}

? 重复零次或⼀一次,等效于{0,1}

{n} 重复n次

{n,} 重复n次或更多次

{n,m} 重复n到m次

Page 10: 正则指引

字符组(Character Classes)

• 匹配若干字符之⼀一,[aeiou]

• 字符组内部,-被作为元字符,表⽰示⼀一个范围,[a-z],放在字符组内最前部,表⽰示-字符

• .?在字符组不作为元字符,[.?!]

Page 11: 正则指引

字符组(Character Classes)

• 缩略表⽰示法,\w,\d,\s

• 排除型字符组,[^0-9],\W,\D,\S

\w 匹配任意字⺟母,数字,下划线,汉字的字符,等效于[a-zA-Z0-9_]

\d 匹配任意数字的字符,等效于[0-9]

\s 匹配任意空⽩白符的字符,等效于∙\f\n\r\t\v

\W 匹配任意不是字⺟母,数字,下划线,汉字的字符

\D 匹配任意⾮非数字的字符

\S 匹配任意不是空⽩白符的字符

[^x] 匹配除了x以外的任意字符

[^aeiou] 匹配除了aeiou这⼏几个字⺟母以外的任意字符

Page 12: 正则指引

多选结构(Alternation)

• 元字符,|,表⽰示或,The|the|THE

• ⽤用()限制多选范围,baidu.(com|org|net)

• 注意各个条件间的顺序,从左往右测试

Page 13: 正则指引

⼦子表达式(subexpression)

• 整个表达式的⼀一部分,元字符 ()

• 量词作⽤用的对象是它们之前紧邻的⼦子表达式,(abc)*

• 分组(Grouping),捕获(Capturing)

Page 14: 正则指引

捕获组(Capturing Group )

• 捕获组是把⼦子表达式匹配的内容,保存到内存中以数字编号或显式命名的组⾥里,⽅方便后⾯面引⽤用

• 引⽤用既可以是在正则表达式内部,也可以是在正则表达式外部

• 普通捕获组,(Expression)

• 命名捕获组,(?<name>Expression)

Page 15: 正则指引

反向引⽤用(backreference)

• 反向引⽤用(\num )⽤用于重复搜索前⾯面某个分组匹配的⽂文本

• 分组规则,从左向右,以分组的左括号为标志,第⼀一个出现的分组的组号为1,第⼆二个为2,以此类推

• (\w)\1,(\w)表⽰示⼀一个分组,\1表⽰示第⼀一分组

Page 16: 正则指引

基础特性就这么多

Page 17: 正则指引

⾮非捕获组(Noncapturing Group)

• 仅⽤用于分组的括号,(?:Expression)

• ⽤用来规定多选结构或者量词作⽤用对象,不⽤用来提取⽂文本

• 能够把复杂的表达式变得清晰,减少引⽤用和分组序号

• 提⾼高匹配效率

Page 18: 正则指引

贪婪与懒惰(Greedy and Lazy)

• 当正则表达式中包含能接受重复的限定符时,通常的⾏行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符

• a.*b匹配abcb,得到abcb

• 懒惰匹配,也就是重复量词匹配尽可能少的字符

• 在量词后⾯面加?,忽略优先量词

• a.*?b匹配abcb,得到ab

*? 重复任意次,但尽可能少重复

+? 重复1次或更多次,但尽可能少重复?? 重复0次或1次,但尽可能少重复

{n,m}? 重复n到m次,但尽可能少重复{n,}? 重复n次以上,但尽可能少重复

Page 19: 正则指引

环视(Lookaround)• 也叫零宽断⾔言(zero-width assertion)

• 环视结构不匹配任何字符,只匹配⽂文本中的特定位置,与\b,^,$相似

肯定顺序环视 (?=Expression) 匹配Expression前⾯面的位置

肯定逆序环视 (?<=Expression) 匹配Expression后⾯面的位置

否定顺序环视 (?!Expression) 匹配后⾯面跟的不是Expression的位置

否定逆序环视 (?<!Expression) 匹配前⾯面不是Expression的位置

Page 20: 正则指引

肯定顺序环视(Positive Lookahead)

• 肯定顺序环视(?=Expression),从左往右检查⽂文本,尝试匹配⼦子表达式,如果能够匹配,就返回成功信息和位置。

• (?=\d)表⽰示如果当前位置的右边字符是数字则匹配成功

• AA(?=BB)和(?=AABB)AA,匹配AABBCC,效果⼀一致

Page 21: 正则指引

否定顺序环视(Negative Lookahead)

• <I>((?!<I>).)*?<\/I>

• <I>x<I>abc</I>x</I>

Page 22: 正则指引

条件判断(?if then |else) Conditionals

• if 部分的测试如果为真(被匹配),尝试使⽤用then,否则使⽤用else(else部分可以不出现)

• if条件部分常常为环视

• (?(?<=NUM:)\d+|\w+)

• 在' NUM: '后的位置匹配\d+,在其他位置匹配\w+

Page 23: 正则指引

固化分组(Atomic Grouping)

• 固化分组抑制回溯的发⽣生

• ⼀一旦⼦子表达式匹配之后,匹配的内容将固定下来,除⾮非整个固化分组都被启⽤用,在外部回溯中重新应⽤用

• 前提是理解正则引擎匹配原理

• A(?>[0-9]+)9,匹配A789失败

Page 24: 正则指引

占有优先量词(Possessive Quantifiers)

• 类似于固化分组的模式,在匹配的过程中不会“交还”中间的结果

• 就功能上⽽而⾔言可以使⽤用固化分组进⾏行模拟

• .++和(?>.+)

• PCRE中对占有优先量词的实现做了⼀一些优化

Page 25: 正则指引

模式修饰符(Mode Modifier)

• 切换正则表达式模式和匹配模式

i 不区分⼤大⼩小写的匹配模式

x宽松排列和注释模式,忽略字符组外部的所有空⽩白,#和换⾏行符之间的内容视为注释

s 单⾏行模式,.能够匹配换⾏行符\n

m 增强的⾏行锚点模式,\A,\Z

(?i)Expression(?-i)!

(?i:Expresssion)!

/Expression/i

Page 26: 正则指引

好了,⾼高级特性也差不多全了

Page 27: 正则指引

引擎分类(Engine Types)

名称 ⼯工具 特点

DFA awk, egrep, MySQL 速度快、功能弱

NFAJava, NET, PCRE, Perl, PHP, Python, Ruby, sed,

vi,emacs速度慢、功能强

• 构建正则表达式的⽅方式决定了某个正则表达式能否匹配⼀一个特定字符串,在何处匹配,以及匹配成功或报告失败的速度。

Page 28: 正则指引

DFA,确定性有穷⾃自动机 (Deterministic Finite Automation)

• ⽂文本主导

• 状态:(aba|abb|abc) 匹配 abcd

• 优势:速度快

• 弊端:不⽀支持括号捕获,不⽀支持环视,不⽀支持“固化分组”

Page 29: 正则指引

NFA,⾮非确定性有穷⾃自动机 (Nondeterministic Finite Automation)

• 表达式主导

• 回溯(最核⼼心)

• 最左最⻓长匹配,匹配成功跳出,可能并不是最⻓长匹配

• a(b)?(b[cd])* 匹配 abcabdbd

Page 30: 正则指引

匹配过程1. 正则表达式编译(检查语法,并编译为内部形式)

2. 传动开始(定位⾄至字符串起始位置)

3. 元素检测(相连元素、量词修饰符、控制权)

4. 寻找匹配结果(NFA找到后锁定,报告匹配成功;DFA继续下⼀一个,找最⻓长结果)

5. 传动装置的驱动过程(没匹配成功,从下⼀一个字符开始)

6. 匹配彻底失败(所有字符尝试完毕,返回彻底失败)

Page 31: 正则指引

回溯(Backtracking)

• 依次处理各个⼦子表达式或组成元素,遇到需要在多个可能成功的位置中进⾏行选择时,它会选择其⼀一,同时记住另⼀一个,以防匹配失败后⽤用另⼀一个分⽀支继续尝试

• 作出选择的情形包括:量词和多选结构

• ⾯面包屑

• a(b)?(b[cd])*

Page 32: 正则指引

备⽤用状态(Saved States)

• ⾯面包屑相当于备⽤用状态

• 在需要的时候,匹配可以从这⾥里重新开始尝试。

• 备⽤用状态保存了两个位置:

• 正则表达式中的位置

• 未尝试的分⽀支在字符串中的位置

Page 33: 正则指引

匹配优先量词原理• hel*o 匹配 hello

• he匹配完后轮到l*

hel*o hello

• 备选状态

hel*o hello

Page 34: 正则指引

匹配优先量词原理

• l*匹配之后

hel*o hello

• 备选状态

hel*o hello

Page 35: 正则指引

忽略优先量词原理• hel*?o 匹配 hello

• he匹配完后轮到l*?

hel*?o hello

• 备选状态

hel*?o hello

• l*?忽略优先直接跳过hel*?o hello

Page 36: 正则指引

占有优先量词原理

• 占有优先量词、固化分组⾥里的⼦子表达式,舍弃备选分⽀支

• (?>.*?)能够匹配什么?

Page 37: 正则指引

正则优化建议• 尽量使⽤用^,$锚点

• .*通常不是最合适的选择

• 字符组/字符识别优化

• 使⽤用⾮非捕获型括号

• 从量词中提取必须元素

• 提取多选结构开头的必须元素

• 将最可能匹配的分⽀支放到多选结构的最前头

• 使⽤用固化分组,放弃备⽤用状态,提⾼高效率

• 能不⽤用正则就不⽤用

Page 38: 正则指引

js-regexp

• https://github.com/kaustubh-karkare/js-regexp

• Pattern,Node,Token,State

• 最核⼼心的设计是扫描正则表达式,根据不同类型Node构建Token,形成Node结构树

• State在匹配过程中记录两个位置,正则表达式中的位置和未尝试的分⽀支在字符串中的位置

Page 39: 正则指引

构建树结构

• a(b)?(b[cd])

• Node.And

• Node.Char(a)

• Node.Loop{0,1}

• Node.Char(b)

• Node.And(capturing group)

• Node.Char(b)

• Node.Or

• Node.Char(c)

• Node.Char(d)

Page 40: 正则指引

“编写正则表达式时,⼀一半时间花在按预期获得成功的匹配,另⼀一半时间⽤用来考虑如何忽略那些不

符合要求的⽂文本。”

Page 41: 正则指引

“要想在复杂性和完整性之间求得平衡,关键是了解你所⾯面对的⽂文本。”

Page 42: 正则指引

“正则不是死板的教条,它更像是艺术。”

Page 43: 正则指引

参考资料 • 《精通正则表达式(第三版)》,Jeffrey.E.F.Friedl

• 《正则指引》,余晟著

• rail-road diagrams,http://www.regexper.com/

• Regex Golf,http://regex.alf.nu/

• Regex Tester,http://regexpal.com/

• RegexBuddy,http://www.regexbuddy.com/ 

• 《正则表达式30分钟⼊入⻔门教程》,http://deerchao.net/tutorials/regex/regex.htm

• 《笔记:如何写出⾼高效率的正则表达式》

• Regular Expressions Cheat Sheet,http://www.cheatography.com/davechild/cheat-sheets/regular-expressions/

Page 44: 正则指引

Q & A