正则笔记-忘记就来看

如果想知道正则在js中的应用可移步:JS中的正则应用

选项(attributes)

js中的正则表达式选项:

  • i 忽略大小写
  • m 处理多行
  • g 全局匹配(查找所有匹配而非在找到第一个匹配后停止)。

元字符(特殊代码)

字符:是计算机软件处理文字时最基本的单位,可能是字母,数字,标点符号,空格,换行符,汉字等等

匹配字符

  • \d 一位数字
  • \D 任意非数字的字符
  • \w 字母或数字或下划线
  • \W 任意不是字母,数字,下划线的字符
  • \n\r 其中\r回车,\n换行符
  • \s 任意的空白符,包括空格,制表符(Tab),换行符,中文全角空格等
  • \S 任意不是空白符的字符
  • . 查找单个字符,除了换行和行结束符。

注意:js中\w匹配不到汉字,在其他语言中有能匹配到汉字的

范围,指定这个范围中的一个字符

  • [aeiou] 里面单个字符是或的关系
  • [^aeiou] 除了aeiou这几个字母以外的任意字符
  • [0-9] 指这个范围中的一个,相当于\d
  • [^x] 除了x以外的任意字符

量词,指定它前边的内容出现的次数,加了量词时正则会表现出贪婪匹配的特性

  • ? 重复0次或1次(表示有或没有),用在量词后面表示尽可能少重复,切换了懒惰匹配的特性
  • + 重复1次或更多次
  • * 连续重复使用任意次(它代表的不是字符,也不是位置,而是数量)
  • {n} 重复n次
  • {n,m} 连续重复n-m次
  • {n,} 重复n次或更多次

其他

  • \b 匹配单词的开始或结束
    虽然通常英文的单词是由空格,标点符号或者换行来分隔的,但是\b并不匹配这些单词分隔字符中的任何一个,它只匹配一个位置。
  • \B 不是单词开头或结尾的位置
  • ^ 匹配字符串的开始([^]这里表示除了的意思)
  • $ 匹配字符串的结束 这两个和\b类似,都只匹配一个位置
  • 选项m和^$一起使用时,就变成了匹配行的开始处和结束处,因此在此模式下,$的精确含意是:匹配\n之前的位置以及字符串结束前的位置.

不常用

  • \t 制表符,Tab
  • \v 竖向制表符
  • (?<x>-<y>exp) 平衡组
  • (?>exp) 贪婪子表达式
  • (?(exp)yes|no) 把exp当作零宽正向先行断言,如果在这个位置能匹配,使用yes作为此组的表达式;否则使用no
  • (?(exp)yes) 同上,只是使用空表达式作为no
  • (?(name)yes|no) 如果命名为name的组捕获到了内容,使用yes作为表达式;否则使用no
  • (?(name)yes) 同上,只是使用空表达式作为no

原文输出需要转译的都是有特殊意义的字符,当然包括所有元字符,但是不包括-

贪婪与懒惰

a.*b:它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配。
a.*?b:匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab(第一到第三个字符)和ab(第四到第五个字符)。这被称为懒惰匹配

为什么第一个匹配是aab(第一到第三个字符)而不是ab(第二到第三个字符)?简单地说,因为正则表达式有另一条规则,比懒惰/贪婪规则的优先级更高:最先开始的匹配拥有最高的优先权

分枝条件(|,又叫或)

正则表达式里的分枝条件指的是有几种规则,如果满足其中任意一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开。使用分枝条件时,要注意各个条件的顺序。匹配分枝条件时,将会从左到右地测试每个条件,如果满足了某个分枝的话,就不会去再管其它的条件了。

分组(())

用法一:重复多个字符

(xxx){num}

用法二:捕获组(分组捕获)

默认情况下,每个分组会自动拥有一个组号
组号分配规则:

  • 分组0对应整个正则表达式
  • 实际上组号分配过程是要从左向右扫描两遍的:第一遍只给未命名组分配,第二遍只给命名组分配,因此所有命名组的组号都大于未命名的组号
  • 你可以使用(?:exp)这样的语法来剥夺一个分组对组号分配的参与权.
  • 自定义组号: (?<Word>\w+)(?'Word'\w+)这样就可以把这个捕获组的组号变成了Word了,再使用反向引用时不能再用\num这种写法,要使用\k<Word>才能拿到内容。

常用分组语法:

分类 代码/语法 说明
捕获 (exp) 匹配exp,并捕获文本到自动命名的组里
(?<name>exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp)
(?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号
零宽断言 (?=exp) (零宽度正预测先行断言)匹配后面跟的是exp的内容
(?<=exp) (零宽度正回顾后发断言)匹配前面是exp的内容
(?!exp) (零宽度负预测先行断言)匹配后面跟的不是exp的内容
(?<!exp) (零宽度负回顾后发断言)匹配前面不是exp的内容
注释 (?#comment) 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读

反向引用(后向引用,不知道哪个名字对,无奈脸。。。)

反向引用用于重复搜索前面某个分组匹配的文本。要结合捕获组使用
正则表达式中想用num号组捕获到的内容再做匹配时,可以写\num

注意:是捕获到的内容,不是捕获组所用的正则

小栗子
\b(\w+)\b\s+\1\b,能匹配到 go go , word word , aaa aaa 等,但是无法匹配到 go to
更改组号写法:\b(?<Word>\w+)\b\s+\k<Word>\b

零宽断言

用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像\b,^,$那样用于指定一个位置,这个位置应该满足一定的条件(即断言),因此它们也被称为零宽断言。
栗子:(?<=<(\w+)>).*(?=<\/\1>)用来匹配不包含属性的简单HTML标签内里的内容。
解析:(?<=<(\w+)>)指定了这样的前缀:被尖括号括起来的单词(比如可能是<b>),然后是.*(任意的字符串),最后是一个后缀(?=<\/\1>)。注意后缀里的\/,它用到了前面提过的字符转义;\1则是一个反向引用,引用的正是捕获的第一组,前面的(\w+)匹配的内容,这样如果前缀实际上是<b>的话,后缀就是</b>了。整个表达式匹配的是<b></b>之间的内容(再次提醒,不包括前缀和后缀本身)。

平衡组/递归匹配

需要匹配可嵌套的层次性结构

语法 说明
(?'group') 把捕获的内容命名为group,并压入堆栈(Stack)
(?'-group') 从堆栈上弹出最后压入堆栈的名为group的捕获内容,如果堆栈本来为空,则本分组的匹配失败
(?(group)yes|no) 如果堆栈上存在以名为group的捕获内容的话,继续匹配yes部分的表达式,否则继续匹配no部分
(?!) 零宽负向先行断言,由于没有后缀表达式,试图匹配总是失败

我们需要做的是每碰到了左括号,就在压入一个"Open",每碰到一个右括号,就弹出一个,到了最后就看看堆栈是否为空--如果不为空那就证明左括号比右括号多,那匹配就应该失败。正则表达式引擎会进行回溯(放弃最前面或最后面的一些字符),尽量使整个表达式得到匹配。
平衡组的一个最常见的应用就是匹配HTML,下面这个例子可以匹配嵌套的<div>标签:<div[^>]*>[^<>]*(((?'Open'<div[^>]*>)[^<>]*)+((?'-Open'</div>)[^<>]*)+)*(?(Open)(?!))</div>.

好吧,我并不知道怎么用平衡组。。。

小知识

  1. 加^$则需要输入的整个字符都需要满足所写的正则匹配规则才可以,如果不加则整个字符串中只要有能匹配上规则的部分即可
  2. ^\w+ 匹配一行的第一个单词(或整个字符串的第一个单词,具体匹配哪个意思得看选项设置)
  3. [.?!] 匹配标点符号(.或?或!)
  4. [^.?!] 匹配除了标点符号.或?或!以外的任意字符

本文主要参考文献

posted @ 2017-02-07 17:22  冰凌哒雪花  阅读(302)  评论(0编辑  收藏  举报