博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
你真的懂JavaScript的正则吗?
阅读量:6256 次
发布时间:2019-06-22

本文共 5989 字,大约阅读时间需要 19 分钟。

本文内容主要出处为《JavaScript权威指南》(第六版),笔者只是在搬砖的同时整理思路,有误望及时指出,感谢!

定义正则表达式

概述

对于正则表达式的概念我们就不多费口舌了...

在JavaScript中使用正则表达式进行模式匹配离不开RegExp对象,创建正则对象有两种方式
1.正则表达式直接量(包含在一对/之间的字符)

var reg = /java/;reg.test('java'); // true复制代码

2.new RegExp()

var reg = new RegExp('java');reg.test('java'); // true复制代码

JavaScript也赋予了String对象进行模式匹配的方法,但是使用这些方法的时候同样离不开RegExp

例如:

var str = 'java';str.match(/java/); // /java/为正则直接量复制代码

StringRegExp 如何进行正则匹配,有哪些方法,会在下面两节讲解,这一节(定义正则表达式),主要讲述如何定义正则表达式(本节会用到RegExptestexec 方法,如若不了解,可以与最后一节结合来理解)

正则——直接字符量

直接字符量表示字符在正则表达式中的表达形式。特殊字符需\转义

字母、数字 -> 自身\o -> NUL字符(\u0000)\t -> 制表符(\u0009)\n -> 换行符(\u000A)\v -> 垂直制表符(\u000B)\f -> 换页符(\u000C)\r -> 回车符(\u000D)...复制代码

正则——字符类

将字符量放入 [] 中就成了字符类,字符类匹配它包含的任意一个字符

[abc] // 表示a 或者b 或者c[^abc] // ^在这里表示取反,除了a、b、c之外的所有字符[a-z] //-表示连接,从a到z的任意字符复制代码

由上面我们可以知道,[0-9]表示任意数字,像这种常用的字符类,JavaScript给他们制订了自己的特殊转义字符。

. // 除换行符与其他Unicode行终止符以外的任意字符\w // 等价于[a-zA-Z0-9_],大小写字母、数字、下划线63字符中任意一个\W // 等价于[^a-zA-Z0-9_]\s // 任何Unicode空白符\S // 任何Unicode非空白符\d // 等价于[0-9]\D // 等价于[^0-9][\b] // \b放入[]中标识退格直接量复制代码

正则——重复

描述相同字符,多次出现

{n, m} // 最少重复n次,最多重复m次{n, } // 至少重复n次{n} //重复n次? // 等价于 {0, 1}+ // 等价于 {1,}* // 等价于 {0,}复制代码

例如:

var reg = new RegExp('a{2,}');var str = 'aaa';var str2 = 'a';reg.test(str); // truereg.test(str2); // false复制代码

在这里会多出一个概念:非贪婪重复

在上述例子中,reg.test(str) === true
我们用reg.exec(str) 获取匹配结果会发现 结果为'aaa'
如果我们选择使用非贪婪重复

var reg = new RegExp('a{2,}?');var str = 'aaa';reg.exec(str);复制代码

这时候结果为 'aa',实现非贪婪重复很简单,在重复后面添加?即可,这时候,正则表达式会尽可能少的去匹配重复。

{n, m} -> {n, m}?{n, } -> {n,}?{n} -> {n}?? -> ??+ -> +?* -> *?复制代码

选择

| 可以分割用于选择的字符,优先级从左向右

ab|cd|ef // 表示 ab 或者 cd 或者 ef复制代码

子模式

() 在包裹子表达式同时将其定义为子模式

我们可以通过 \index 这种写法在同一个正则表达式中调用子模式, index表示子模式的索引,从1开始。

var reg1 = /(java)script and \1/;var reg2 = /javascript and java/;// reg1 与 reg2 是两个基本等价的正则直接量var str = 'javascript and java';reg1.test(str); // truereg2.test(str); // true复制代码

子模式还有助于我们抽取子表达式匹配结果

把上述例子改为用exec方法并且打印

var reg1 = /(java)script and \1/;var reg2 = /javascript and java/;var str = 'javascript and java';console.log(reg1.exec(str));console.log(reg2.exec(str));复制代码

输出结果为:

可以看到,当存在子模式时候,结果集会添加其子模式匹配结果,从中我们也可以看出,为什么子模式
index的索引会从1开始,因为0是完整的正则匹配结果。

当然,JavaScript允许我们在使用子表达式的时候不生成子模式

使用(?: )来包裹子表达式

var reg = /(?:java)script and java/;复制代码

此时我们无法通过\1找到其子模式,也无法获取其子模式的匹配结果。

指定匹配位置

^ // 字符串开始位置(在字符类中表示取反)$ // 字符串的结束位置\b // 单词边界,也就是\w与\W的边界(?=p) // 要求字符串与p匹配,但是结果集并不包含匹配p的字符(?!p) // 要求字符串不与p匹配复制代码

^ 与 $

/^javascript/ // 字符串以javascript开始/javascript$/ // 字符串以javascript结束复制代码

\b

var reg = /\bjava\b/;var str1 = 'java';var str2 ='javascript';var str3 = 'java c++';var str4 = 'html java c++';reg.test(str1); // truereg.test(str2); // falsereg.test(str3); // truereg.test(str4); // true在这里 \b 匹配非\w字符,包括字符串起始与结束。\B与之相反,匹配非单词边界处复制代码

(?=)

var reg = /java(?=script)/;var str = 'java';var str1 = 'javascript';reg.exec(str); // 匹配失败 , 因为不包含scriptreg.exec(str1); // 此时匹配成公,但是匹配结果并不包含script复制代码

输出结果为:

(?!)
var reg = /java(?!script)/;var str = 'javaee';var str1 = 'javascript';reg.exec(str); // 匹配成功,匹配结果为javareg.exec(str1); // 匹配失败,因为包含script复制代码

修饰符

i // 不区分大小写m // 匹配多行(使用^ $指定起止时候能通融\n换行)g // 匹配成功第一处,并不会继续停止,会继续寻找所有匹配复制代码

通过直接量创建正则对象添加修饰符: /java/gim (使用多个修饰词直接并列)

通过构造函数创建正则对象添加修饰符: new RegExp(reg , 'gim');

通过String的模式匹配

String对象提供四种方法用于正则匹配。

search()

str.search(reg)

匹配成功返回起始位置,失败返回-1,在search方法中修饰词g不生效

var str = 'hello java';str.search(/java/); // 6str.search(/^java/); // -1复制代码

match()

str.match(reg)

匹配失败返回null,匹配成功返回的是一个由匹配结果组成的数组。如果该正则 表达式设置了修饰符g,则该方法返回的数组包含字符串中的所有匹配结果。

var str = 'hello java and javascript';str.match(/java/); str.match(/java/g);复制代码

输出结果为:

replace()

两种调用方式,第二个参数不同

  • str.replace(reg , replaceStr)

    var str = 'javaee javaee';// str1 = 'javascript javaee'var str1 = str.replace(/e{2}/ , 'script'); // str2 = 'javascript javascript' 修饰符g表示全局替换var str2 = str.replace(/e{2}/g , 'script'); // 补充知识点:str 依然是 javaee ,至于原因,简单说就是字符串直接量不可改变,字符串所有的有关于值的改变的方法都是return新值。复制代码

    第二个参数replaceStr,用于替换的字符串有一些特殊的写法

    var reg = /"([^"]*)"/g; // 匹配 "" 间的内容,且内容不包含"var str = '"java","c++" and "html"';var str1 = str.replace(reg , '“$1”');console.log(str1) // “java”,“c++” and “html”复制代码

    此时,$1表示子模式([^"]*)匹配的结果集, 与我们上一节定义正则表达式中的调用自己的子模式\1相仿。

    同样,在此处$还有其他几种用法

    $index // 就是上述例子中的$1$& // 表示原字符串  -> "java","c++" and "html"$` // 匹配字符串的左侧值,在上述例子中匹配成功三次,分别为: 空值 、 "java", 、"java","c++" and $' // 匹配字符串的右侧值,在上述例子中匹配成功三次,分别为: ,"c++" and "html" 、  and "html" 、空值$$ // 字符常量$复制代码
  • str.replace(reg , function)

    var reg = /"([^"]*)"/g; // 匹配 "" 间的内容,且内容不包含"var str = '"java","c++" and "html"';var str1 = str.replace(reg , function (...arr) {  console.log(arr)});复制代码

    输出结果为:

    匹配成功了三次,所以输出了三次arr数组,这个数组里面的元素分别为:

    0: 匹配结果
    ...: 若存在子模式,这里为子模式匹配结果
    last - 1: 索引位置
    last: 原字符串

    我们可以根据自己想要的结果,动态替换内容,通过return将结果替换到新的字符串中。

    var reg = /"([^"]*)"/g; // 匹配 "" 间的内容,且内容不包含" var str = '"java","c++" and "html"'; var str1 = str.replace(reg , function (...arr) {  return `“${arr[1]}”` }); console.log(str1) // “java”,“c++” and “html”复制代码

    split()

    • str.split(分隔符)
      根据分隔符分割返回新数组
    • str.split(reg)
      根据正则分割返回新数组
      var str = 'a,b-c,e,f-g';var arr = str.split(/[,-]/);console.log(arr) // ['a','b','c','d','e','f','g']复制代码

通过RegExp的模式匹配

构造函数

var reg = new RegExp('\\w'); // 通过正则表达式字符串var reg1 = new RegExp(/\w/); // 通过正则表达式直接量var reg2 = new RegExp(reg , 'gim'); // 第二个参数为修饰符复制代码

属性

  • source: String 正则表达式文本值
  • global: Boolean 是否携带全局修饰符g
  • ignoreCase:Boolean 是否携带忽略大小写修饰符i
  • multiline:Boolean 是否携带匹配多行修饰符m
  • lastIndex: Number 如果global === true , 那么这个参数记录每次匹配后的索引位置,下面的testexec方法会用到

方法

  • reg.exec(str)
    如果匹配失败,返回null,匹配成功,返回匹配结果,每次执行仅返回一个匹配结果,若global === true,每次匹配成功后,会把lastIndex 属性设置为紧挨着 匹配子串的字符位置。再次调用此方法,会从当前位置开始匹配(当我们使用同一个RegExp匹配新的字符串的时候,最好把lastIndex属性设置为0)
    var reg = new RegExp('java' , 'g');var str = 'javascript java javaee';var result = reg.exec(str);while (result) {  console.log(result)  console.log(`lastIndex = ${reg.lastIndex}`)  result = reg.exec(str);}复制代码
    输出结果为:

当我们通过正则表达式直接量来调用进行正则运算的时候,并不会出现这种情况,那是因为在ES5中,每次通过直接量进行正则运算,JavaScript都会生成新的RegExp对象。

  • reg.test(str)
    test方法与exec基本等价,不同的是他们的返回值,test比较简单粗暴,当exec返回null时候,它返回false,其他情况返回true

转载地址:http://fansa.baihongyu.com/

你可能感兴趣的文章
非均衡数据分布的分类问题
查看>>
用JAVA代码构造一个日历
查看>>
oracle密码过期ORA-28002:口令将过期的解决方法
查看>>
webdriver css选取器
查看>>
浏览器窗口最大化
查看>>
B+树
查看>>
[转] Yslow-网站性能评分工具的图文解析
查看>>
简单工厂设计模式计算器
查看>>
WinFrom“动态”WebService
查看>>
【钢铁侠3】【高清1280版HD-RMVB.英语中字】【2013最新美国票房科幻动作大片】...
查看>>
Eclipse 修改JVM
查看>>
状态者模式 c#
查看>>
最长回文子串
查看>>
Node-mongodb链接数据库函数的封装
查看>>
在CentOS上简单安装tengine
查看>>
c语言——字符串变量、函数
查看>>
解决Type safety: The expression of type List needs
查看>>
POJ 3233 (矩阵)
查看>>
20161220
查看>>
11月27日
查看>>