正则表达式
一、前言
虽然园子里已经有很多人总结过正则了,但自己不主动整理下,别人的永远是别人的,自己动手后才不会那么快遗忘。正则表达式用事先定义好的一些特定字符及这些特定字符的组合,组成一个“规则字符串”,用这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式本身作为一门语言,学习方式类似其他语言,先学词(元字符),然后学语法,最后拼接字符表达出自己想要表达的含义。
二、正则元字符
- 字符
字符 字符说明 示例 示例说明 \w 与数字、字符、下划线以及汉字匹配 \d 与十进制数字字符匹配 \s 与任何空白字符匹配(空格、制表符、换行等) \W 与不是数字、字符、下划线以及汉字的字符匹配 \D 与非数字字符匹配 \S 与非空白字符匹配 [character_group] 与character_group中指定的任意单个字符匹配 [abc] 匹配gray中的a [^character_group] 与character_group中指定字符之外任意字符匹配 [^abc] 匹配gray中的g、r、y [first-last] 与指定范围中的任意单个字符匹配 [a-z1-9] 匹配abCD2中的a、b、2 [^first-last] 与指定范围外的任意字符匹配 [^a-z1-9] 匹配abCD2中的C、D . 与换行符以外的任意字符匹配 character_group 与character_group指定的字符集匹配 ra 匹配gray中的ra \ 字符转义 1\.9 匹配1.98中的1.9 - 数量词
字符 字符说明 示例 示例说明 * 匹配上一个元素零次或多次 \d*\.\d 匹配88.88中的88.8,.88中的.8 + 匹配上一个元素一次或多次 \d+\.\d 匹配88.88中的88.8 ? 匹配上一个元素零次或一次 \d?\.\d 匹配88.88中的8.8,.88中的.8 {n} 匹配上一个元素n次 \d{1}\.\d 匹配88.88中的8.8 {n,} 匹配上一个元素至少n次 \d{1,}\.\d 匹配88.88中的88.8 {n,m} 匹配上一个元素n到m次 \d{1,3}\.\d 匹配8888.88中的888.8 *? 匹配上一个元素零次或多次,但次数尽可能少 1\d*? 匹配1888.88中的1 +? 匹配上一个元素一次或多次,但次数尽可能少 1\d+? 匹配1888.88中的18 ?? 匹配上一个元素零次或一次,但次数尽可能少 1\d?? 匹配1888.88中的1 {n,} 匹配上一个元素至少n次,但次数尽可能少 1\d{2,} 匹配1888.88中的188 {n,m} 匹配上一个元素n到m次,但次数尽可能少 1\d{2,5} 匹配1888.88中的188 - 定位点
字符 字符说明 示例 示例说明 ^ 匹配字符串的开头 ^\w{2} 匹配123456中的12 $ 匹配字符串末尾 \w{2}$ 匹配123456中的56 \b 匹配字符(\w)的边界(开始、结束) \b\w{2}\b 匹配123 45 678中的45 \B 匹配非字符边界的位置 bc\B 匹配abc abcd 中第二个bc
三、正则语法
- 分支
在编码的时候,通常有这么一种场景,字符串满足“条件1”或者“条件2”,幸运的是正则提供了类似其他语言或运算功能,当然符号也很类似,示例如下:
\b189\d{8}|\b159\d{8} 表达式匹配189开头或者159开头且长度为11的字符串。
注意:正则匹配分支顺序从左到右,若左边分支匹配成功则不再匹配剩下的条件。比较这两个表达式有什么不同 \d{5}-\d{4}|\d{5} \d{5}|\d{5}-\d{4} - 分组
前面的示例中介绍了如何用数量词重复单个字符,例如:1\d*。那么如何重复多个字符呢?正则可以使用小括号将待重复的字符包裹起来,然后使数量词作用于被小括号包裹的整个字符集上,示例如下:
0\.(13)+ 表达式匹配0.13,13无限循环小数。
正则使用小括号指定分组后,这个分组匹配的文本,默认会缓存起来,供表达式后续使用。
分组匹配的文本每个组都自动拥有一个编号,从左向右以左小括号为标志,第一个组编号为1,依次递增。编号0表示整个正则表达式
正则指定分组时可单独为每个组指定组名,在组号分配时优先给未命名的组分配编号,然后再给指定组名的分组分配编号,因此组号分配过程需要扫描两次表达式。
js不支持分组命名
语法 语法说明 (exp) 捕获匹配exp的字符串,并为其分配一个从1开始的编号 (?<group_name>exp) 捕获匹配exp的字符串,并为其指定组名group_name,也可以写成(?'group_name'exp) (?:exp) 匹配exp,不捕获字符串,也不分配组号 - 向后引用
向后引用用于重复搜索前面某个分组匹配的文本,\1表示分组1匹配的文本,\k<group_name>或者\k'group_name'表示组名为group_name分组匹配的文本。示例如下:
\b(\w+)\b\s+\1\s+\1\b 捕获三次重复的单词,例如:go go go
\b(?<name>\w+)\b\s+\k<name>\s+\<name>\b 捕获三次重复的单词,例如:go go go。 - 零宽断言
前面介绍正则元字符的时候提到定位点(^、$等),但是有时候我们需要自定义一些定位点,例如位置ing。像^指定一个位置,这个位置满足某种条件(即断言),我们称之为零宽断言。
断言跟前面的定位点一样分为前瞻、后瞻,js不支持后瞻断言。正向断言会消耗字符,负向断言不消耗字符。
语法 语法说明 示例 示例说明 (?=exp) 零宽度正向前瞻,匹配后面跟的是exp的位置 \b\w+(?=ing) 匹配I am writing a blog中的writ (?!exp) 零宽度负向前瞻,匹配后面不是跟的exp的位置 \b\w{4}(?!ing) 匹配I am writing a blog中的blog (?<=exp) 零宽度正向后瞻,匹配前面跟的是exp的位置 (?<=wri)\w+\b 匹配I am writing a blog中的ting (?<!exp) 零宽度负向后瞻,匹配前面不是跟的exp的位置 (?<!wri)\w{4}\b 匹配I am writing a blog中的blog
四、其他
- 正则在线工具
http://regexr.com/ - 参考链接
本文主要介绍了正则的一些基础属性,若需使用此文未介绍的特性可查阅以下链接
https://msdn.microsoft.com/zh-cn/library/az24scfc.aspx
http://deerchao.net/tutorials/regex/regex.htm