前言

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

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

正则表达式是什么?

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

怎么创建?

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

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

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

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

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

flag标识

如果指定,标志可以具有以下值的任意组合:

g : 全局匹配;找到所有匹配,而不是在第一个匹配后停止

i : 忽略大小写

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匹配的文本。

注意,这个不适合这样使用([...]),不适合包括在方括号里,这样的必须后面出现的跟第一次出现的匹配类型一致。
例如,/^([a-z\d])\1$/,可以是字母也可数字,但是第一次出现的数字的话,后面必须也是数字这个表达式才会正确用。

这个例子去运行一下就知道应用场景和意义了:'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'],大家注意到第二个元素了没,就是括号捕获的内容了,是不是比用零宽断言简单好多咧

最后

如果你有正则匹配问题,欢迎咨询,尽量为你解答。

喜欢请点赞~转载注明出处谢谢~写文章不易,用手机写的,如有格式问题请谅解

转载于:https://juejin.im/post/5b640f5ee51d4535c7564d40

这是一篇男女老少入门精通咸宜的正则笔记相关推荐

  1. 一篇 vSAN 入门,送给大家

    一篇 vSAN 入门,送给大家 https://mp.weixin.qq.com/s?__biz=MzUxODgwOTkyMQ==&mid=2247484078&idx=1&s ...

  2. 零基础学python需要多久-Python要学习多久能入门?精通需要多久?

    学习Python是大家进入编程世界的首选,在学习Python之前不少人都会关注学习时间和周期的问题,Python需要学多久可以入门?精通需要多长时间呢?为大家详细的介绍一下. 自学Python需要多久 ...

  3. 数独游戏技巧从入门到精通_中国茶艺技巧:500集从入门到精通教程,视频+素材+笔记...

    中国茶艺技巧:500集从入门到精通教程,视频+素材+笔记 学习茶艺可以增加生活中的兴趣爱好,多一门技能,多一项生存能力,将传统文化进行一种简单快乐的传播.以生活为中心,将喜爱为半径,沏一杯美好生活茶. ...

  4. 一篇“从入门到上手”的Solidworks机械设计教程

    一篇"从入门到上手"的Solidworks机械设计教程 机器人专业的学生,多多少少总需要和机械结构打点交道.有时候可能是做个安装设备的架子,有时候可以需要个简单的运动机构,这些简单 ...

  5. 如何配置Thymeleaf教程,及Thymeleaf的简单使用教程【一篇足够入门】

    如何配置Thymeleaf教程,及Thymeleaf的简单使用教程[一篇足够入门] 第一步[进行maven项目的建立(maven的建立前面文章中有提过),建立完之后在pom.xml中进行相关包的导入跟 ...

  6. 一篇“从入门到上手”的PCB设计教程

    一篇"从入门到上手"的PCB设计教程 这是一篇面向神马都不懂的小白玩家的PCB设计教程.希望能帮助大家快速上手PCB的设计. 1 预备知识 1.1 常用工具 (1)做图工具:Alt ...

  7. numpy基础篇-简单入门教程4

    numpy基础篇-简单入门教程4 np.set_printoptions(precision=3),只显示小数点后三位 np.random.seed(100)rand_arr = np.random. ...

  8. HDTV入门扫盲篇HDTV入门

    HDTV入门扫盲篇HDTV入门 1,什么是HDTV? 要解释HDTV,我们首先要了解DTV.DTV是一种数字电视技术,是目前传统模拟电视技术的接班人.所谓的数字电视,是指从演播室到发射.传输.接收过程 ...

  9. 零基础新手自学Python编程教程入门精通学习资料网站大全

    零基础新手自学Python编程教程入门精通学习资料网站大全 今天说下关于Python的一些普及知识,以及学习资料,这一节我来跟大家分享下. 1 为什么要学习Python? 1 Python是一个脚本语 ...

最新文章

  1. 虚拟机上安装ArchLinux笔记
  2. JS判断元素是否在数组内
  3. 函数字节不对齐函数崩溃_Excel中统计字符数,不需要一个一个的数,len函数能轻松搞定...
  4. python里面temp是啥-python temp file:如何打开多次临时文件?
  5. Ext.grid.Panel表格分页
  6. NLP预训练模型学习全攻略(内附前沿论文解读直播)
  7. RecyclerView用法--展示多种类型Item数据
  8. ‘复杂变简单‘的代码例子
  9. mysql my.ini my.cnf_Mysql配置文件my.ini/my.cnf
  10. [递归]递归问题解题思路
  11. 【华为云技术分享】Linux内核的分布式编译(1)
  12. 从前台获取的数据出现乱码的解决方法
  13. asp.net 通过context.RewritePath和ashx开发接口
  14. 《产品经理面试攻略》PART 2:简历
  15. python中pow_Python中float的内置pow()和math.pow()之间的区别?
  16. IBM Cognos 10.2 最新体验之旅
  17. 电脑磁盘数据错误(循环冗余检查)的原因以及解决办法
  18. STM32DIY机械键盘
  19. setup/teardown用法汇总
  20. windows自带录屏_电脑录屏有哪些快捷键?设置帮助电脑快速录屏

热门文章

  1. sonarlint 规范
  2. PluginOK中间件产品介绍
  3. html中点击A超链接使其不跳转
  4. css中.prepend,js prepend() 和append()区别
  5. 10种主要的统计学习方法总结
  6. 网络分析系列之一 网络数据包分析基础知识
  7. 经典游戏---贪吃蛇从C++代码实现
  8. promise对象里resolve和reject状态讲解及Promise.all()的使用
  9. 如何1秒钟让程序员抖腿?教你10个方法!
  10. 如何让自己每天都过得很充实很开心--论制定计划目标的重要性