js正则表达式详解

正则表达式

正则表达式并不是JavaScript里面独有的技术,基本上所有的编程语言都支持这个技术。

正则表达式有以下几个特点【它的特点也可以认为是它的使用场景】

  1. 正则表达式只对字符串进行操作
  2. 正则表达式做的是根据你所设定的规则对字符串进行“验证”,“提取”,“搜索”,“替换”等操作
  3. JavaScript中的正则表达式是一个内置对象,它可以直接使用,它使用RegExp构造函数来创建,或直接使用字面量表示法/正则规则/

正则表达式分为三个部分

正则表达式
模式规则
修饰符
方法

正则表达式的创建

正则表达式它是一个对象,我们要使用对象的方法去创建它的,它的构造函数是RegExp,它的语法如下

第一种创建方式

var reg = new RegExp(pattern: string | RegExp, flags?: string): RegExp

上面的pattern代表的是规则,后面的flags代表的是修饰符

所以根所据上面的语法要求,我们可以偿试着去创建一个正则

var reg1 = new RegExp("爱");   //这就是最基本的正则表达式创建
var reg2 = new RegExp("","g");	//这里就添加了一个修饰符

第二种创建方式

这一种创建方式我们叫字面量创建,它直接使用/规则/这种方式来创建

var reg2 = //;
console.log(reg2);
console.log(typeof reg2);

上面就是正则表达式的创建过程,在学习正则表达式的过程当中,我们先了解正则表达式的两个方法

  1. test()方法,用于验证某个字符串是否符合这个正则表达式规则
  2. exec()方法,用于根据正则表达式去字符串中提取符合要求的字符

根据上面的两个方法,我们才可以学习正则表达式

同时要注意,正则表达式在创建的过程当中,它还可以添加修饰符flags,主要的修饰符有3个

  1. g代表全局global的意思
  2. i代表ignore忽略大小写
  3. m代表multipleline多行的意思,也就是可以换行查找

正则表达式的规则

一元符
元字符对应说明
.匹配除换行符之外的任意字符
\w匹配字母数字下划线,等同于:[a-zA-Z0-9_]
\s匹配任意空白符
\d匹配数字,等同于[0-9]
\b匹配单词边界
|或匹配,如 /x|y/ 正则可匹配x或y两个字符
^匹配字符串的开始
$匹配字符串的结束
原子表与原子组

原子表

 //现在我希望匹配以下的东西杨标,陈标,张标
// 原子表指的是[]
// 原子组指的是()
var reg = /^[杨陈张]标$/;
reg.test("杨标");		//true
reg.test("陈标");		//true
reg.test("张标");		//true
reg.test("李标");     //false

原子表是以中括号的形式存在,它会从这个表中拿一个出来进行匹配

在原子表里面,还可以写区间范围

var reg1 = /[a-z]/;  //代表小写字母
var reg2 = /[A-Z]/;  //代表大写字母
var reg3 = /[0-9]/;  //代表数字,相当于\d

注意:原子表中的范围不能倒着写,写反了会报错

原子组

//现在我希望匹配以下的东西杨标,陈标,张标
var reg = /杨标|陈标|张标/;
var reg1 = /[杨陈张]标/;
//上面的正则表达式是符合要求的,但是很繁琐
var reg2 = /(杨|陈|张)标/;
//如果是用小括号包起来,就是原子组

原子组后期的优点非常多

var str = "大家好,今天是2021-01-06 14:48:30,今天天气不好,有点冷";

var reg = /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/;

var result = reg.exec(str);   //通过正则表达式提取的结果

上面的案例就是通过原子组来进行的二次提取操作

反义字符
反义字符对应说明
[^x]匹配除“x”之外的所有字符,其中“x”可以为任意字符
[^xyz]同上,匹配除“x、y、z”之外的任意字符
\W匹配除了字母、数字、下划线之外的所有字符,等同于:[^\w]
\S匹配除空白符之外的任意字符,等同于:[^\s]
\B匹配不是单词边界的字符,等同于:[^\b]
\D匹配不是数字的所有字符,等同于:[^\d]
转义字符
转义字符对应说明
\xnn匹配十六进制数
\f匹配换页符,等同于:\x0c
\n匹配换行符,等同于:\x0a
\r匹配回车符,等同于:\x0d
\t匹配水平制表符,等同于:\x09
\v匹配垂直制表符,等同于:\x0b
\unnnn匹配Unicode字符,如:\u00A0

正则表达式里面一些特殊的东西是需要转义的,如[,],/,.{,},+,*,?等,转义需要使用\表示

重复匹配
匹配字符对应说明
*重复出现零次或多次
+重复出现一次或多次
重复出现零次或一次
{n}重复出现n次
{n,}至少重复出现n次
{m,n}重复重现m到n次,其中,m<n
//我们希望验证一个字符串,它是a开始,以c结束。中间有4个英文字母怎么办呢
var reg = /^a[a-zA-Z]c$/;
//第一种写法,直接写4次,这是笨办法
var reg1 = /^a[a-zA-Z]{4}c$/;

//验证一个字符串,它是a开始,c结束,中间有4~6个数字,怎么办
var reg2 = /^a\d{4,6}c$/;

//验证一个字符串,它是a开始,c结束,中间有至少4个数字,怎么办
var reg3 = /^a\d{4,}c$/;

上面的写法是我们的m-n的写法,还有一些特殊的写法

//验证一个字符串,以a开始,c结束,中间可以有1个或多个数字
var reg4= /^a\d{1,}c$/;
//或
var reg5 = /^a\d+c$/;   //+号代表1次多或次

//验证一个字符串,以a开始,以c结束,中间有0次或多次出数字
var reg6= /^a\d*c$/

//有一个姓名,它以杨开始,以标结束,中间可以有1个或0个字符,怎么办呢
var reg =  /^杨.?标$/
贪婪与惰性
相关字符对应说明
*?重复任意次,但尽可能少的重复
+?重复一次或多次,但尽可能少的重复
??重复零次或一次,但尽可能少的重复
{m,n}?重复m到n次,但尽可能少的重复
{n,}?重复n次以上,但尽可能少的重复
var str = "cbcertydiouycesdfsertd";

//我的要求,提取以c开始,d结束,中间是任何长度的英文字母
var reg = /c[a-z]*d/;
// 这个时候的正则是有问题的,*处理贪婪模式,它会贪式,(*代表0次到多次,它会贪多次)
//如果我们直接以reg为标准去匹配,我们会发现,它会从头匹配到尾,但是字符串中间是是有符合要求的

var reg2 = /c[a-z]*?d/g;
  • 贪婪模式:尽可能的选取多个【婪多个】
  • 惰性模式:尽可能少取以个【懒惰】

在禁止贪婪模式以后,就会变成惰性模式,它会尽可能的少重复

原子组编号

在我们之前学习原子组的时候我们学过,可以将规则通过()来形成一个分组,其实在形成分组的时候,默认会形成一个分组编号

var str = "<div></div>";
//现在希望编写一个正则去验证HTML的标签
//初步的思维
var reg1 = /<[a-zA-Z0-9]+><\/[a-zA-Z0-9]+>/;

在上面的正则表达式当中,我们表面看起来是已经完成了功能,但是有隐患,如果我们的字符串是<div></span>这个时候它也会验证成功,这是不符合要求的

我们要求的是开始标签名与结束标签名保持一致。我开始匹配的内容[a-zA-Z0-9]+要与后面匹配的[a-zA-Z0-9]+保持一致,这怎么办呢,这个时候就要使用到原子组编号

var reg2 = /<([a-zA-Z0-9]+)><\/\1>/;

后面正则表达式所出现的\1代表的是匹配出来的第1个分组内容

我们还可以通过下面的案例来学习分组

var str = "fdafffdaaklfjklja";
//现在要求找出字符串中连续重复的字符串
var reg = /(\w)\1+/g;
str.match(reg);  //这样就可以得到结果了

当然原子组的编号不仅仅只有1个,可以实现多个组的编号,如下

var str ="ababcdefaceced1212rtioio4ybyb";
//在里面找出那些有规律的两个一起重复的字符串
var reg =/(\w)(\w)\1\2/g;
str.match(reg);

分组不产生原子组编号

()分组产生分组号

(?:)分组不产生原子组编号

在正常情况下,原子组当中只要有了小括号就会在提取的时候产生编号,如下所示

var str = "今天是9月10日,唉呀!今天又跑到香港去玩了,买了好多东西,购物花了我¥346.77元,结果吃饭只能用美元,花了我$34.78元,坐港铁花了¥11元。";
var reg = /(?<=[\$¥])\d+(\.\d+)?/g;
reg.exec(str);
//得到结果如下
var reg = /(?<=[\$¥])\d+(?:\.\d+)?/g;
前瞻后顾

在弄清楚之个东西之前,先要让同学们知道什么是正则表达式的前后关系

在学习这个地方之前,还一定要弄清楚,

  1. 你的匹配条件是什么?
  2. 你的限制条件是什么?
前瞻

前瞻(Look ahead positive): 匹配的是A,限制条件是A后面是B。

A(?=B)

想要匹配abc并且abc的后面是123的表达式,应该这样

在这里插入图片描述

负前瞻

负前瞻(Look ahead negative): 顾名思义,该正则匹配A,限制条件是A后面不是B

A(?!B)

匹配abc并且abc的后面面不是123的表达式,应该这样:

在这里插入图片描述

后顾

后顾(Look behind positive ): 匹配表达式A,限制条件A的前面是B

(?<=B)A

匹配abc并且abc的后面是123的表达式
在这里插入图片描述

负后顾

负后顾(Look behind negative ): 匹配表达式A,限制条件是A的前面不是B

(?<!B)A

匹配abc并且abc的后面不是123的表达式,应该这样:
在这里插入图片描述

正则表达式的操作方法

方法说明
String.prototype.replace()字符串替换
String.prototype.search()字符串查找
String.prototype.match()字符串匹配提取
String.prototype.split()字符串根据正则表达式分割
RegExp.prototype.test()根据正则规则验证字符串
RegExp.prototype.exec()根据正则表达式规则提取字符串
test()验证

这是正则表达式的一个方法,用于验证一个字符串是否符合正则的要求,如果符合就返回true,不符合就返回false

//正则表达式的验证是test方法,它是正则对象的方法
/**
     * 验证用户名,必须字母或下划线开头,后面接任意非空字符,总长度在6~10位
     * 验证年龄:必须是正整数
     * 验证性别:必须是男或女
     * 验证爱好:必须是 看书,睡觉,玩游戏三者之顺选择,可以选多个
*/

var reg1 = /^[a-z]\S{5,9}$/i;
reg1.test("a123abd");

var reg2 = /^\d+$/;
reg2.test("12");

var reg3 = /^[男女]$/;

//这个正则要去掉重复的情况
var reg4 = /(看书|睡觉|玩游戏)+/;
exec()提取
var str ="今天是9月10日,唉呀!今天又跑到香港去玩了,买了好多东西,购物花了我¥346.77元,结果吃饭只能用美元,花了我$34.78元,坐港铁花了¥10元。";
//在上面的字符串里面,我们要提取所有的金额(美圆和人民币)

第一种方式的操作:手动操作

//在上面的字符串里面,我们要提取所有的金额(美圆和人民币)
var str = "今天是9月10日,唉呀!今天又跑到香港去玩了,买了好多东西,购物花了我¥346.77元,结果吃饭只能用美元,花了我$34.78元,坐港铁花了¥11元。";
var reg = /(?<=[\$¥])\d+(\.\d+)?/g;
var result = "";
//第一次提取						//346.77
result = reg.exec(str);
console.log(result);
//第二次提取						//34.78
result = reg.exec(str);		
console.log(result);
//第三次提取						//11
result = reg.exec(str);
console.log(result);
//第四次提取						//null
result = reg.exec(str);
console.log(result);

第二种方式的操作:使用循环

var result = "";
while ((result = reg.exec(str)) != null) {
    console.log(result);
}

这一种正则表达式的提取是一种非常高级的提取方法,我们可以在复杂操作里面使用这个方法,但是一般简单的提取操作,我们会使用更简单的方法


match()提取
//match方法不是正则表达式对象的方法,它是字符串对象的方法
//match方法是匹配的意思,根据正则表达式来匹配
var str = "今天是9月10日,唉呀!今天又跑到香港去玩了,买了好多东西,购物花了我¥346.77元,结果吃饭只能用美元,花了我$34.78元,坐港铁花了¥11元。";
//在上面的字符串里面,我们要提取所有的金额(美圆和人民币)
var reg = /(?<=[\$¥])\d+(?:\.\d+)?/g;
//以前是使用正则表达式为主体,去操作字符串
//现在是以字符串为主体,去匹配正则
var result = str.match(reg);   //['346.77', '34.78', '11']

在上面的代码里面,我们可以看到,match方法与正则表达式对象里面的exec方法都是用于提取符要求的字符的,但是exec可以做到原子组的提取,而match则不行,如下所示

var str = "我的身份证号是425789199011150105,张三的身份证号是12355420050405233x";
    //写一个正则,提取字符串,并提取每个人性别组成对象
    /*
        [{
            IDCard:"425789199011150105",
            birthday:"1990-11-15",
            sex:"女"
        },{
            IDCard:"12355420050405233x",
            birthday:"2005-05-05",
            sex:"男"
        }]
    */

    var reg1 = /\d{17}[\dx]/g;
    var result1 = str.match(reg1); //['425789199011150105', '12355420050405233x']

    //上面明显不是最好的处理办法

    var reg2 = /\d{6}(\d{4})(\d{2})(\d{2})\d{2}(\d{1})[\dx]/g;
    var result2 = "";
    var arr = [];
    while ((result2 = reg2.exec(str)) != null) {
        var obj = {
            IDCard: result2[0],
            // birthday:result2.slice(1,4).join("-"),
            birthday: result2[1] + "-" + result2[2] + "-" + result2[3],
            sex: result2[4] % 2 == 0 ? "女" : "男"
        }
        arr.push(obj);
    }
    console.log(arr);

注意:无论是exec()还是match() 在目前阶段进行提取操作的时候,最后是加一个全局修饰符g

split()分割

字符串的split方法之前我们已经讲过了,它是通过某一个特定的字符去拆分字符串形成数组

var str = "get-element-by-id";
var arr = str.split("-");   //["get", "element", "by", "id"];


var str1 = "我们是123club组合我们的的年龄是19岁身高都在170公分以上";
//希望通过中间在数字去拆分 ["我们是","club组合哈组合我们的的年龄是","岁身高都在","公分以上"];
var reg1 = /\d+/;
var arr1 = str1.split(reg1);
search()搜索

之前在字符串里面,我们可以通过search查找某个字符串的索引位置,只是那个时候使用是indexOf

以前的情况下面

var str1 = "大家好,我是人见人爱的张三,我的身高是170CM!";
var str2 = "大家好,我是高富帅李四,我的身高是186CM!";
var str3 = "大家好,我是美女西施,我的身高是169CM!";
var str4 = "大家好,我是古典成熟高质量男性小乐乐,我的身高是178CM!";
//在上面的字符串当中,找所有的数字的位置
str1.indexOf("170");
str2.indexOf("186");
str3.indexOf("169");
str4.indexOf("178");
//这个参数在变化,如果这里有100个变量,我就有可能要写100句话
str1.search(/\d+/g);
str2.search(/\d+/g);
str3.search(/\d+/g);
str4.search(/\d+/g);
//这个时候的参数就固定成了一个正则表达式
replace()替换

它是字符串的方法

var str = "我爱你,你爱我吗?";
var str1 = str.replace("爱","恨");  //"我恨你,你爱我吗?";

replace方法默认情况下只会替换第一个匹配项,不会全局匹配,所以如果要全局匹配,则只能使用正则

var str = "我爱你,你爱我吗?";
var str2 = str.replace(//g,"恨");		//"我恨你,你恨我吗";

当我们所查找替换的元素一旦是通过正则匹配的,则replace()第二个参数就变了,它变成了一个回调函数

var str = "我爱你,你爱我吗?";
str.replace(//g, function (p) {
    // 第一个参数:p代表正册表达式的匹配项
    console.log(p);
});

当正则表达式里面有原子组的时候

var str = "大家好,今天是2021-01-06 14:48:30,今天天气不好,有点冷";
var reg = /\d{4}-(\d{2})-\d{2}\s(\d{2}):\d{2}:\d{2}/g;
str.replace(reg, function (p,g1,g2) {
    // 第一个参数:正则匹配的结果
    // 第后面开始的参数则代表原子组编号 group1   group2
    console.log(p);
    console.log(g1);
    console.log(g2);
})

上面的01就是原子组1的结果,02就是原子组2的结果

// 给一个连字符串例如:get-element-by-id转化成驼峰形(推荐使用正则表达式+replace的方式完成)
var str1 = "get-element-by-id";
//getElementById;
var str2 = str1.replace(/-([a-z])/g,function(p,g1){
    // console.log(p,g1);
    return g1.toUpperCase();
})

总结

  1. 正则只对字符串进行操作
  2. 正则的创建方式要弄清楚
  3. 正则的规则
    • 一元符
    • 原子组与原子表
    • 重复匹配
    • 原子组编号
    • 前瞻后顾
  4. 使用到正则的地方目前所接触只有String对象与RegExp对象

  • 2
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值