javascript正则表达式入门先了解这些
前言
此内容由学习《JavaScript正则表达式迷你书(1.1版)》整理而来(于2020年3月30日看完)。此外还参考了MDN上关于Regex和String的相关内容,还有ECMAScript 6中关于正则的扩展内容,但不多。在文章末尾,会放上所有的链接。
迷你书共七章,我都做了相应的标号。不过我将【7】7种方法放在了前面,讨论了具体情境下怎么正确使用函数的问题(其实是我自己一直被这个问题困扰,书上的例子为什么用这个方法,为什么这个方法这里返回这样,那里却不是这样,把我搞崩溃了),也建议大家先搞懂这个吧。
本文重点
正则的 2 种创建
正则的 6 个修饰符(i、g、m、u、y、s)
【7】.用到正则的 7 种方法(RegExp(exec、test),String(search、match、matchAll、replace、split))
正则表达式中的6种结构(字符字面量、字符组、量词、锚、分组、分支)
【1】.字符匹配:字面量、字符组、量词。重点还有贪婪匹配与惰性匹配
【2】.位置匹配:^ 、$ 、 \b 、\B 、(?=abc) 、 (?!abc) 的使用
【3】.括号的作用:分组和分支结构。知识点有:分组引用($1的使用)、反向引用(\1的使用)、括号嵌套、括号结合量词
【4】.回溯原理 (本文大多介绍的是实践中用的基础知识,后期对此可能会单独写篇,先占个坑)
【5】.正则的拆分:重点是操作符的优先级
【6】.正则表达式的构建(本章写了些提高正则准确性和效率的内容,也先占个坑)
简单实用的正则测试器
2种创建
语法:/pattern/flags
var regexp = /\w+/g;
var regexp = new RegExp('\\w+','g');
6个修饰符

重点介绍全局与非全局:
全局就是说在字符串中查找所有与正则式匹配的内容,因此会有>=1个结果。
而为了得到这个所谓的所有匹配内容的过程,后面介绍的函数还有一次执行和多次执行之别。
如果正则表达式中存在分组,该模式下各个函数返回的结果也不一样。
非全局就简单了,它表示匹配到了一个就不会再继续往后匹配了,因此都是一次就得结果。
7种方法
以下图在我学习的过程中,修改了很多遍,才得出了这个最简洁明了的版本。


【补充1】全局模式对 exec 和 test 的影响
正则实例有个 lastIndex 属性,表示尝试匹配时,从字符串的 lastIndex 位开始去匹配。
全局匹配下,字符串的四个方法,每次匹配时,都是从 0 开始的,即 lastIndex 属性始终不变。
而正则实例的两个方法 exec、test,当正则是全局匹配时,每一次匹配完成后,都会修改 lastIndex。(详见下面示例)
如果是非全局匹配,自然都是从字符串第 0 个字符处开始尝试匹配:
exec()在全局状态下,需要一次次执行直到末尾才能得到所有匹配项,这里只是手动模拟下。当然最好是用循环实现,while ((match = regexp.exec(str)) !== null) {//输出}
var regexp = /a/g;
console.log( regexp.exec("a"), regexp.lastIndex );// [ 'a', index: 0, input: 'a', groups: undefined ] 1
console.log( regexp.exec("aba"), regexp.lastIndex );// [ 'a', index: 2, input: 'aba', groups: undefined ] 3
console.log( regexp.exec("ababc"), regexp.lastIndex );// null 0
注意:该部分将的所有正则表达式不知道的都先不要急,慢慢来。
【补充2】全局下match、exec、matchAll示例
match()和exec()示例:
//全局模式下,匹配所有能匹配到的
var regexp1 = /t(e)(st(\d?))/g;
var str1 = 'test1test2';
console.log(str1.match(regexp1)); //match返回所有匹配项组成的数组[ 'test1', 'test2' ]
console.log(regexp1.exec(str1))// exec第一次执行返回第一个匹配项和它的分组['test1', 'e','st1','1',index:0,input:'test1test2',groups:undefined]
console.log(regexp1.exec(str1))//exec第二次执行返回第二个匹配项和它的分组['test2', 'e','st2','2',index:5,input:'test1test2',groups:undefined]
console.log(regexp1.exec(str1))//exec第二次执行已经到末尾了,因此第三次结果为null
//非全局模式下,只匹配到第一项就停止
var regexp2 = /t(e)(st(\d?))/;
var str2 = 'test1test2';
console.log(str2.match(regexp2)); //match['test1', 'e','st1','1',index:0,input:'test1test2',groups:undefined]
console.log(regexp2.exec(str2)) //exec['test1', 'e','st1','1',index:0,input:'test1test2',groups:undefined]
matchAll()示例:
matchAll()是es6的用法,记住它返回的就是一个迭代器。可以用for...of循环取出,也可以用...迭代器运算符或者Array.from(迭代器)将它转为数组。
var array1 = [...str1.matchAll(regexp1)];
console.log(array1)
//['test1','e','st1','1',index: 0,input: 'test1test2',groups: undefined]
//['test2','e','st2','2',index: 5,input: 'test1test2',groups: undefined]
var array2 = [...str2.matchAll(regexp2)];
console.log(array2)
//['test1','e','st1','1',index: 0,input: 'test1test2',groups: undefined]

到目前为止,我们应该积攒了很多问号了。我学的过程中有以下两个问题:
1./t(e)(st(\d?))/g和/t(e)(st(\d?))/的区别我知道了,但t(e)(st(\d?))这是什么意思呢?
2.上文所谓的“与正则表达式匹配的内容”和“匹配项中分组捕获的内容”怎么理解?
那就带着问题看后面的内容吧。
7种结构 -字符匹配
字面量

字符组
需要强调的是,虽叫字符组(字符类),但只是其中一个字符。
如果字符组里的字符特别多,可用连字符 - 来省略和简写(见表格示例)。
示例:全局匹配,使用match()方法返回字符串中与表达式匹配的所有内容。[123]表示这个位置的字符可以是1、2、3中的任意一个


量词
有了一个字符,那我我们就会考虑到需要它出现几次,那么量词来了。
示例:全局匹配,使用match()方法返回字符串中与表达式匹配的所有内容。b{2,5}表示字符b出现2到5次。


贪婪匹配与惰性匹配

贪婪匹配/\d{2,5}/ 表示数字连续出现 2 到 5 次,会尽可能多的匹配。你如果有 6 个连续的数字,那我就要我的上限 5 个;你如果只有 3 个连续数字,那我就要3个。想要我只取 2 个,除非你只有两个。
惰性匹配/\d{2,5}?/ 表示虽然 2 到 5 次都行,当 2 个就够的时候,我也不贪,我就取两个。
对惰性匹配的记忆方式是:量词后面加个问号,问一问你知足了吗,你很贪婪吗?注意是 量词后面 量词后面 量词后面,重要的事说三遍。还是来个例子吧,?与??:
'testtest1test2'.match(/t(e)(st(\d?))/g)的结果就是[ 'test', 'test1', 'test2' ]
'testtest1test2'.match(/t(e)(st(\d??))/g)的结果就是[ 'test', 'test', 'test' ]
7种结构 -位置匹配
位置理解

位置特性
1.对于位置的理解,我们可以理解成空字符 ""。
因此,把 /^hello$/ 写成 /^^hello$$$/,是没有任何问题的。甚至 /(?=he)^^he(?=\w)llo$\b\b$/;
2.整体匹配时,自然就需要使用 ^ 和 $

7种结构 - 括号的作用
分组和分支结构
到目前为止,我们对于 match(/t(e)(st(\d?))/g)应该完全理解了(包括 match()的使用,全局修饰符g,表示字符组的\d和表示量词的?,且也知道了这是贪婪匹配)。那么,里面的括号又表示什么意思呢?这就涉及到分组捕获了。
以日期为例,假设要匹配的格式是 yyyy-mm-dd 的:

对比这两个可视化图片,我们发现,与前者相比,后者多了分组编号,如 Group #1,这样正则就能在匹配表达式的同时,还能得到我们想要从匹配项中捕获的分组内容。即用 () 括起来的内容。到此为止,t(e)(st(\d?))涉及到的分组捕获知识点也就结束了。
再介绍下分支结构,由于操作符 | 的优先级最低,因此需要将其放于括号中:
分支结构形如(regex1|regex2),字面意思,即这里可以匹配 regex1或者 regex2之一,捕获分组的时候也是二者之一 ,例子:

引用分组
使用相应 API 来引用分组。
提取数据

替换replace

当第二个参数是字符串时,如下的字符有特殊的含义。其中,第二个是 $&:

反向引用分组
除了使用相应 API 来引用分组,也可以在正则本身里引用分组。但只能引用之前出现的分组,即反向引用。
以前面的日期为例,假设我们想要求分割符前后一致怎么办?即杜绝 2016-06/12这样中间分割符不一致的情况,此时需要使用反向引用:
注意里面的 \1,表示的引用之前的那个分组 (-|\/|\.)。不管它匹配到什么(比如 -),\1 都匹配那个同样的具体某个字符。
我们知道了 \1 的含义后,那么 \2 和 \3 的概念也就理解了,即分别指代第二个和第三个分组。需要注意:
\10表示第十个分组,如果真要匹配\1和0的话,使用(?:\1)0或者\1(?:0)。反向引用引用不存在的分组时候,匹配
反向引用的字符本身。例如\2,就匹配"\2"。

分组括号嵌套
针对 "1231231233".match(/^((\d)(\d(\d)))\1\2\3\4$/) 的可视化形式如下,一目了然:

分组括号结合量词
分组后面有量词的话,分组最终捕获到的数据是最后一次的匹配。分组引用与反向引用都是这样例子:

非捕获括号
如果只想要括号最原始的功能,但不会引用它,即,既不在 API 里引用,也不在正则里反向引用。
可以使用非捕获括号 (?:p) 和 (?:p1|p2|p3),如下代码,执行matchAll(),虽然有括号,但不会得到捕获的分组内容。

正则的拆分
不仅要求自己能解决问题,还要看懂别人的解决方案。代码是这样,正则表达式也是这样。如何能正确地把一大串正则拆分成一块一块的,成为了破解“天书”的关键。
这里,我们来分析一个正则 /ab?(c|de*)+|fg/:

思考下:
/^abc|bcd$/和/^(abc|bcd)$/。
/^[abc]{3}+$/和/^([abc]{3})+$/
操作符优先级

操作符转义
所有操作符都需要转义
^、$、.、*、+、?、|、\、/、(、)、[、]、{、}、=、!、:、- ,
用\符号进行转义

到这里,对正则表达式也算是入了个小门了,即对正则的一些基本操作也有了了解,也能看懂别人的正则表达式,就算是copy也能灵活的改动了。
简单实用的正则测试器
效果图:

源代码:git
相关链接
老姚 《JavaScript 正则表达式迷你书》下载
阮一峰《ECMAScript 6 入门 - 正则的扩展》
MDN RegExp.prototype.exec()
MDN RegExp.prototype.test()
MDN String.prototype.search()
MDN String.prototype.match()
MDN String.prototype.matchAll()
MDN String.prototype.replace()
MDN String.prototype.split()
javascript正则表达式入门先了解这些的更多相关文章
- 正则系列——JavaScript正则表达式入门心得
我发现有个别字符被这个编辑器给刷掉了,但是灰色区域显示正常,以灰色区域代码为准 什么玩意? 在我刚开始学习编程的时候,就听过正则了,也听说正则很牛逼,懂正则的更牛逼.但是苦于没有人指点,也没有使用正则 ...
- JavaScript 正则表达式入门教程
正则表达式是描述一组字符串特征的模式,用来匹配特定的字符串 主要分三个部分:基本语法.RegExp对象的方法.JS中支持正则表达式的String对象方法 一.基本语法 在JS中,正则表达式为对象,用如 ...
- javascript正则表达式入门
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...
- JavaScript正则表达式详解(一)正则表达式入门
JavaScript正则表达式是很多JavaScript开发人员比较头疼的事情,也很多人不愿意学习,只是必要的时候上网查一下就可以啦~本文中详细的把JavaScript正则表达式的用法进行了列表,希望 ...
- 正则表达式入门教程&&经典Javascript正则表达式(share)
前言 例子: ^.+@.+\\..+$ 这样的代码曾经多次把我自己给吓退过.可能很多人也是被这样的代码给吓跑的吧.继续阅读本文将让你也可以自由应用这样的代码. 正文 教程:正则表达式30分钟入门教程 ...
- 正则表达式基于JavaScript的入门详解
关于正则表达式,和很多前辈聊起这个知识点时,他们的反馈都比聊其他技术谦逊,而和很多刚入门的程序员讨论时甚至会有觉得你看不起他. 的确,正则表达式从通常的应用来看,的确不难,比如电话,邮箱等验证.语法, ...
- 正则表达式入门教程&&经典Javascript正则表达式----share
前言 例子: ^.+@.+\\..+$ 这样的代码曾经多次把我自己给吓退过.可能很多人也是被这样的代码给吓跑的吧.继续阅读本文将让你也可以自由应用这样的代码. 正文 教程:正则表达式30分钟入门教程 ...
- 正则表达式入门教程&&经典Javascript正则表达式
前言 例子: ^.+@.+\\..+$ 这样的代码曾经多次把我自己给吓退过.可能很多人也是被这样的代码给吓跑的吧.继续阅读本文将让你也可以自由应用这样的代码. 正文 教程:正则表达式30分钟入门教程 ...
- javascript 正则表达式 详细入门教程
1.什么是正则表达式 定义: 一个用来搜索.匹配.处理一些符合特定语法规则的一个强大的字符串处理工具. 用途: 进行特定字符和字符串的搜索 替换字符串中指定的字符或字符串 验证字符串是否符合需求 2. ...
随机推荐
- Scheme实现数字电路仿真(3)——模块
版权申明:本文为博主窗户(Colin Cai)原创,欢迎转帖.如要转贴,必须注明原文网址 http://www.cnblogs.com/Colin-Cai/p/12242650.html 作者:窗户 ...
- Ubuntu 18.04安装搜狗输入法
Ubuntu 18.04安装搜狗输入法 打开 terminal,输入 fcitx,检查是否安装搜狗输入法依赖,若提示未安装使用以下命令安装 sudo apt-get install fcitx-bin ...
- Ado.net01
------------恢复内容开始------------ 1.ExcuteReader using System; using System.Data.SqlClient; using Syste ...
- web前端性能优化的技巧
1. 请减少HTTP请求 基本原理: 在浏览器(客户端)和服务器发生通信时,就已经消耗了大量的时间,尤其是在网络情况比较糟糕的时候,这个问题尤其的突出. 一个正常HTTP请求的流程简述:如在浏览器中输 ...
- 网站开发---js与java实现的一些小功能
记录一下网站开发过程中的一些小功能 1.js获取当前年份: <span>Copyright © 2017-<script>document.write( new Date(). ...
- Linux——如何将Red Hat Enterprise Linux 6的语言改为中文?
第一步,打开终端,输入su -,获取超级用户权限,输入密码. 第二步,输入cd /etc/sysconfig,进入设置目录. 第三步,输入vi i18n,进入到配置文件. 第四步,按 ‘i’键,进入编 ...
- GPS北斗NTP校时服务器原理及功能介绍
在科技的发展下GPS北斗NTP校时服务器也得到了广泛应用,比如工业.科研.航空航天.公共场所等领域都用到了GPS北斗NTP校时服务器,该时间服务器以卫星时间为基准授时准确,替代了传统钟表授时的单一和时 ...
- MySQL数据库常用命令行整理(表格)
Laplace Kang 2020-03-13T08:33:09Z 2020-03-14T17:35:53Z Sheet1 12480 9 600 600 6 9600 23040 0 0 600 0 ...
- redis 出现(error) MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details
如果在ubuntu安装的redis含端口使用,但是某些时候常常出现 (error) MISCONF Redis is configured to save RDB snapshots, but is ...
- ES6整体内容
ES6内容: 附网站链接:http://www.jscwwd.com/article/5e6488e849a13d1a89caf574