热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

javascript–正则表达式入门先了解这些

前言此内容由学习《JavaScript正则表达式迷你书(1.1版)》整理而来(于2020年3月30日看完)。此外还参考了MDN上关于Regex和String的相关内容,还有ECMA

前言

此内容由学习《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]表示这个位置的字符可以是123中的任意一个


量词

有了一个字符,那我我们就会考虑到需要它出现几次,那么量词来了。

示例:全局匹配,使用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 的概念也就理解了,即分别指代第二个和第三个分组。需要注意:



  1. \10表示第十个分组,如果真要匹配 \10 的话,使用 (?:\1)0 或者 \1(?:0)



  2. 反向引用引用不存在的分组时候,匹配

    反向引用的字符本身。例如 \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()



推荐阅读
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 标题: ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 深度学习中的Vision Transformer (ViT)详解
    本文详细介绍了深度学习中的Vision Transformer (ViT)方法。首先介绍了相关工作和ViT的基本原理,包括图像块嵌入、可学习的嵌入、位置嵌入和Transformer编码器等。接着讨论了ViT的张量维度变化、归纳偏置与混合架构、微调及更高分辨率等方面。最后给出了实验结果和相关代码的链接。本文的研究表明,对于CV任务,直接应用纯Transformer架构于图像块序列是可行的,无需依赖于卷积网络。 ... [详细]
  • Python爬虫中使用正则表达式的方法和注意事项
    本文介绍了在Python爬虫中使用正则表达式的方法和注意事项。首先解释了爬虫的四个主要步骤,并强调了正则表达式在数据处理中的重要性。然后详细介绍了正则表达式的概念和用法,包括检索、替换和过滤文本的功能。同时提到了re模块是Python内置的用于处理正则表达式的模块,并给出了使用正则表达式时需要注意的特殊字符转义和原始字符串的用法。通过本文的学习,读者可以掌握在Python爬虫中使用正则表达式的技巧和方法。 ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • Gitlab接入公司内部单点登录的安装和配置教程
    本文介绍了如何将公司内部的Gitlab系统接入单点登录服务,并提供了安装和配置的详细教程。通过使用oauth2协议,将原有的各子系统的独立登录统一迁移至单点登录。文章包括Gitlab的安装环境、版本号、编辑配置文件的步骤,并解决了在迁移过程中可能遇到的问题。 ... [详细]
author-avatar
卧龙先生八斗才
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有