这是一篇男女老幼入门精通咸宜的正则笔记

未经容许,请勿私自转载正则表达式

前言

说句实话的,自从我整理这篇笔记后,基本上项目里遇到的全部正则匹配的问题,不论多复杂,只要回过头看这篇笔记,理解透彻(请注意个人用词描述,我这里描述比较严谨,理解好中文意思更方便你理解正则意义。这是个文字游戏[奸笑]),基本上都能解决的。这里关于深内容的描述,我这边也举了很多内容帮助你们理解。express

这是一篇男女老幼入门精通咸宜的正则笔记。数组

正则表达式是什么?

字符是计算机软件处理文字时最基本的单位,字符串是0个或更多个字符的序列。 在编写处理字符串的程序或网页时,常常会有查找符合某些复杂规则的字符串的须要。正则表达式就是用于描述这些规则的工具,就是来用于匹配字符串中字符组合的模式。浏览器

怎么建立?

正则表达式字面量
/ pattern / flag
调用RegExp对象的构造函数
new RegExp(pattern, flag)
这里的pattern,有三种形式:bash

  1. 参数变量
  2. 带引号的匹配模式
  3. 带//的匹配模式

注意:带引号的方式,须要常规的字符转义规则(在前面加反斜杠 \),而带//的方式,则跟字面量形式同样。函数

E.g. 都表示同一个规则工具

var re = new RegExp("\\w+");
var re = new RegExp(/\w+/);
var re = /\w+/;
复制代码

flag标识

若是指定,标志能够具备如下值的任意组合:测试

g : 全局匹配;找到全部匹配,而不是在第一个匹配后中止ui

i : 忽略大小写spa

m : 多行; 将开始和结束字符(^和$)视为在多行上工做(例如,分别匹配每一行的开始和结束(由 \n 或 \r 分割),而不仅是只匹配整个输入字符串的最开始和最末尾处。

区别:
当正则表达式保持为常量时使用字面量;若是你知道正则表达式模式将会改变,或者你事先不知道什么模式,而是从另外一个来源获取,如用户输入,这些状况均可以使用构造函数。

规则

简单匹配,精确匹配
常见的特殊字符

特殊字符 描述
\b 匹配一个词的边界。\b匹配这样的位置:它的前一个字符和后一个字符不全是(一个是,一个不是或不存在)\w。注意,一个匹配的词的边界并不包含在匹配的内容中,跟^$同样,或者能够这么理解:因为这是个位置,因此匹配出来天然就没东西了。
举例说明:
一个字符串reading books,\b匹配的是哪里呢?画个图,看表格最下方图一。就是橙色线的位置就是\b的位置了
\w 匹配一个单字字符(字母、数字或者下划线)
\s 匹配一个空白字符,包括空格、制表符、换页符和换行符。
\d 匹配一个数字。匹配的是正整数,且匹配检查的对象是数字类型时,如1. 会当成1 处理,即/^\d$/.test(1.)返回true,/^\d$/.test(‘1.’)返回false;
. (小数点)匹配除换行符以外的任何单个字符。
[\u4e00-\u9fa5] 匹配汉字
匹配前面一个表达式0次或者1次。等价于 {0,1}。若是紧跟在任何量词 *、 +、?或 {} 的后面,将会使量词变为非贪婪的(匹配尽可能少的字符),和缺省使用的贪婪模式(匹配尽量多的字符)正好相反。
* 匹配前一个表达式0次或屡次。等价于 {0,}。
+ 匹配前面一个表达式1次或者屡次。等价于 {1,}。
{n} n是一个正整数,匹配了前面一个字符恰好发生了n次

{n,m}

n 和 m 都是正整数。匹配前面的字符至少n次,最多m次。若是 n 或者 m 的值是0, 这个值被忽略。
^ 匹配输入的开始。若是多行标志被设置为true,那么也匹配换行符后紧跟的位置。当'^'做为第一个字符出如今一个字符集合模式时,它将表示“非”
$ 匹配输入的结束。若是多行标示被设置为true,那么也匹配换行符前的位置。
| x|y,匹配‘x’或者‘y’。匹配分枝条件时,将会从左到右地测试每一个条件,若是知足了某个分枝的话,就不会去再管其它的条件了。
[ ] 一个字符集合。匹配方括号的中任意字符,包括转义序列。你可使用破折号(-)来指定一个字符范围。不过[.?!*]匹配标点符号(.或?或!或*)。他们没必要进行转义,不过转义也是起做用的。
[^] 当 '^'做为第一个字符出如今一个字符集合模式时,它将表示“非”。并且是对于其后的全部表达式取非,而不是紧接其后的一个表达式。 匹配的结果为不是这些字符的字符。
[^aei]匹配除了aei这几个字母之外的任意字符,注意是单独取非,即不能出现a或e或i,而不是不能出现aei这个总体字符串。
例如:/[^aei]/.test('a'),结果为false,由于他出现了a。再如/[^aei]/.test('as'),结果为true,由于这里的有出现s,知足既不为a也不为e也不为i。
\ 在非特殊字符以前的反斜杠表示下一个字符是特殊的,不能从字面上解释。反斜杠也能够将其后的特殊字符,转义为字面量。使用 new RegExp("pattern")的时候不要忘记将 \ 进行转义,由于 \ 在字符串里面也是一个转义字符。

此外,对应还有\B \W \S \D,都匹配跟上面小写的意思相反

正则表达式里的单词是什么意思吧:就是很多于一个的连续的\w。


图一:

“(”和“)”也是元字符,须要时也是要使用转义的。

规则 描述
(x) 使用小括号指定一个子表达式后,匹配这个子表达式的文本(也就是此分组捕获的内容)能够在表达式或其它程序中做进一步的处理。
(?:x) 匹配 'x'可是不记住匹配项。这种叫做非捕获括号,不给此分组分配组号

(?x)

匹配x,并捕获文本到名称为name的组里,也能够写成 (?'name'x)

这里详细说说关于 (x)

默认状况下,每一个分组会自动拥有一个组号,规则是:分组0对应整个正则表达式实际上组号分配过程是要从左向右扫描两遍的:第一遍只给未命名组分配,第二遍只给命名组分配--所以全部命名组的组号都大于未命名的组号

可使用(?:exp)这样的语法来剥夺一个分组对组号分配的参与权。

后向引用用于重复搜索前面某个分组匹配的文本。
例如,\1表明分组1匹配的文本。

注意:
这个不适合对“范围值”使用,即不能一看就知道是表明哪一个字符的状况使用,如\d\w或利用中括号表示某些范围的值等状况,由于你用\d来判断时,此刻你不知道\d表明具体哪一个数字。假如你仍然对这些“范围值”使用后向引用的话,引用的值必须跟第一次出现的值要如出一辙。
例如,/^([a-z\d])\1$/,能够是字母也可数字,可是第一次出现的数字的话,后面必须也是数字,且必须是同一个数字,这个表达式才会匹配出true

这个例子去运行一下就知道应用场景和意义了:'2018-09-87'.match(/^(\d{1,4})(-|/)(\d{1,2})\2(\d{1,2})$/)

零宽断言

即零宽度断言,断言就是判断条件,零宽度就是匹配出来的内容是零,表现跟上述的\b^$同样,也是用来匹配位置的。

规则 描述

(?=x)

匹配这么一个位置:后面接着出现的是匹配表达式x。
好比\b\w+(?=ing\b),匹配以ing结尾的单词的前面部分(除了ing之外的部分)。 如查找I'm singing while you're dancing.时,它会匹配sing和danc。
如表格下放的图二所示,因此匹配出来的结果是橙线和蓝线之间的内容,即上述表达的\w+部分
(?<=x) 匹配这么一个位置:前面接着出现的是匹配表达式x。
好比(?<=\bre)\w+\b会匹配以re开头的单词的后半部分(除了re之外的部分),例如在查找reading a book时,它匹配ading。如表格下放的图三所示
(?!x) 匹配这么一个位置:后面接着出现的不能是匹配表达式x。
例如:\d{3}(?!\d)匹配三位数字,并且这三位数字的后面不能是数字
(?<!x) 匹配这么一个位置:前面接着出现的不能是匹配表达式x。

图二:

图三:


这里有兼容性问题,有些浏览器只支持正向的零宽断言即(?=exp)和(?!exp),不支持负向零宽断言。并且就算浏览器支持了,可能你的编译工具在运行编译时也会报错。

值得一提,有个经典的用法,也是运用到零宽断言,假设有个需求须要匹配一个字符串里不能包含某个字符串。例如,判断一个字符串里不能包含hello
正则表达式: ^((?!hello).)*$
若是用test()来校验的话,那么只要这个字符串里包含hello,就会为false。固然其实这种需求并不须要这么麻烦去处理。直接用/hello/.test(somestring),而后取反就能识别了。

贪婪与懒惰

当正则表达式中包含能接受重复的限定符时,一般的行为是(在使整个表达式能获得匹配的前提下)匹配尽量多的字符。

以这个表达式为例:a.*b,它将会匹配最长的以 a开始,以b结束的字符串。若是用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配。

有时,咱们更须要懒惰匹配,也就是匹配尽量少的字符。前面给出的限定符均可以被转化为懒惰匹配模式,只要在它后面加上一个问号?。
这样.*?就意味着匹配任意数量的重复,可是在能使整个匹配成功的前提下使用最少的重复。

a.*?b匹配最短的,以a开始,以b结 束的字符串。若是把它应用于aabab的话,它会匹配aab(第一到第三个字符)和ab(第四到第五个字符)。 为何第一个匹配是aab(第一到第三个字符)而不是ab(第二到第三个字符)?

简单地说,由于正则表达式有另 一条规则,比懒惰/贪婪规则的优先级更高:** 最早开始的匹配拥有最高的优先权。**
懒惰模式适用于 * ? + {} 后面;

还有一个很好例子说明懒惰模式的用处,'{{f}},fas{{fsfsf}}a{{fsa}}'.match(/{{.+?}}/g)。 这个就能把一个字符串里全部{{}}的最小单位给筛选出来,能够去控制台里输出看看

怎么用?

被用于 RegExp 的 exec 和 test 方法, 以及 String 的 match、replace、search 和 split 方法。

exec()

语法
regexObj.exec(str)
返回值
若是匹配成功,exec()方法返回一个数组,并更新正则表达式对象的属性。返回的数组将彻底匹配成功的文本做为第一项,将正则括号里匹配成功(即括号捕获)的做为数组填充到后面。
若是匹配失败,exec() 方法返回 null。

test()

语法
regexObj.test(str)
返回值
若是正则表达式与指定的字符串匹配,返回true;不然false。

search()

语法
str.search(regexp)
参数regexp,一个正则表达式(regular expression)对象。若是传入一个非正则表达式对象,则会使用 new RegExp(obj)隐式地将其转换为正则表达式对象。
返回值
若是匹配成功,则search()返回正则表达式在字符串中首次匹配项的索引。不然,返回 -1。

match()

语法
str.match(regexp);
参数regexp,一个正则表达式对象。若是传入一个非正则表达式对象,则会隐式地使用 new RegExp(obj) 将其转换为一个RegExp。若是你未提供任何参数,直接使用 match() ,那么你会获得一个包含空字符串的 Array :[""] 。
返回值
一个包含了整个匹配结果以及任何括号捕获的匹配结果的 Array ;若是没有匹配项,则返回 null 。
描述
若是正则表达式没有 g 标志,则str.match()会返回和 RegExp.exec()相同的结果。
相比有g,返回的Array拥有一个额外的input属性,该属性包含被解析的原始字符串。另外,还拥有一个index属性,该属性表示匹配结果在原字符串中的索引(以0开始)。

若是正则表达式包含 g 标志,则该方法返回一个 Array ,它包含全部匹配的子字符串而不是匹配对象。捕获组不会被返回(即不返回index属性和input属性)。若是没有匹配到,则返回 null 。

注意

  1. 只有用match方法才能体现g的意义
  2. 注意返回值,其中有个描述是会返回括号捕获结果,这个信息很是重要。举个例子说明其重要性:针对这么一个字符串CrawlerName":"BW","Sis":444',获取“BW”这个字符串。若是用正则匹配出来?

第一反应,使用上述的零宽断言,运行一下脚本

'"CrawlerName":"BW","Sis":444'.match(/(?<="CrawlerName":").*(?=",)/)
复制代码

返回值为一个数组—— ['BW']

然而,可能浏览器不支持负向零宽断言,因此找个通用的办法,这时候就要发挥match返回括号捕获的功能了。运行一下脚本

'"CrawlerName":"BW","Sis":444'.match(/"CrawlerName":"(.*)",/)
复制代码

这时候返回['"CrawlerName":"BW",', 'BW'],你们注意到第二个元素了没,就是括号捕获的内容了,是否是比用零宽断言简单好多咧

最后

若是你有正则匹配问题,欢迎咨询,尽可能为你解答。

喜欢请点赞~~写文章不易,用手机写的,若有格式问题请谅解

未经容许,请勿私自转载

相关文章
相关标签/搜索