正则表达式

一、前言

  虽然园子里已经有很多人总结过正则了,但自己不主动整理下,别人的永远是别人的,自己动手后才不会那么快遗忘。正则表达式用事先定义好的一些特定字符及这些特定字符的组合,组成一个“规则字符串”,用这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式本身作为一门语言,学习方式类似其他语言,先学词(元字符),然后学语法,最后拼接字符表达出自己想要表达的含义。

二、正则元字符

  1. 字符
    字符 字符说明 示例 示例说明
    \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



















  2. 数量词
    字符 字符说明 示例 示例说明
    * 匹配上一个元素零次或多次  \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


















  3. 定位点
    字符 字符说明 示例 示例说明
    ^ 匹配字符串的开头  ^\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. 分支
    在编码的时候,通常有这么一种场景,字符串满足“条件1”或者“条件2”,幸运的是正则提供了类似其他语言或运算功能,当然符号也很类似,示例如下:
    \b189\d{8}|\b159\d{8}  表达式匹配189开头或者159开头且长度为11的字符串。
    注意:正则匹配分支顺序从左到右,若左边分支匹配成功则不再匹配剩下的条件。比较这两个表达式有什么不同    \d{5}-\d{4}|\d{5}    \d{5}|\d{5}-\d{4}
  2. 分组
    前面的示例中介绍了如何用数量词重复单个字符,例如:1\d*。那么如何重复多个字符呢?正则可以使用小括号将待重复的字符包裹起来,然后使数量词作用于被小括号包裹的整个字符集上,示例如下:
    0\.(13)+    表达式匹配0.13,13无限循环小数。

    正则使用小括号指定分组后,这个分组匹配的文本,默认会缓存起来,供表达式后续使用。
    分组匹配的文本每个组都自动拥有一个编号,从左向右以左小括号为标志,第一个组编号为1,依次递增。编号0表示整个正则表达式
    正则指定分组时可单独为每个组指定组名,在组号分配时优先给未命名的组分配编号,然后再给指定组名的分组分配编号,因此组号分配过程需要扫描两次表达式。
    js不支持分组命名
    语法 语法说明
    (exp) 捕获匹配exp的字符串,并为其分配一个从1开始的编号
    (?<group_name>exp) 捕获匹配exp的字符串,并为其指定组名group_name,也可以写成(?'group_name'exp)
    (?:exp) 匹配exp,不捕获字符串,也不分配组号






  3. 向后引用
    向后引用用于重复搜索前面某个分组匹配的文本,\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。
  4. 零宽断言
    前面介绍正则元字符的时候提到定位点(^、$等),但是有时候我们需要自定义一些定位点,例如位置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







 四、其他

  1. 正则在线工具
    http://regexr.com/
  2. 参考链接
    本文主要介绍了正则的一些基础属性,若需使用此文未介绍的特性可查阅以下链接
    https://msdn.microsoft.com/zh-cn/library/az24scfc.aspx
    http://deerchao.net/tutorials/regex/regex.htm
posted @ 2016-12-28 11:27  NikLiu  阅读(545)  评论(0编辑  收藏  举报