正则表达式

regular expression : RegExp

用来处理字符串的规则

  • 只能处理字符串
  • 它是一个规则:可以验证字符串是否符合某个规则(test),也可以把字符串中符合规则的内容捕获到(exec/match…)
let str = "good good study,day day up!";
//=>学正则就是用来制定规则(是否包含数字)
let reg = /\d+/;
reg.test(str);  //false
str = "2020-07-05";
reg.exel(str); //=>["2020", index: 0, input: "2020-07-05"]

编写正则表达式

创建方式有两种

//=>字面两创建方式(两个斜杠之间包起来的,都是用来描述规则的元字符)
let reg1 = /\d+/;
//=>构造函数模式创建 两个参数:元字符字符串,修饰符字符串
let reg2 = new RegExp("\\d+");

正则表达式由两部分组成

  • 元字符
  • 修饰符
/*常用的元字符*///=>1.量词元字符,设置出现的次数
*     0到多次
+     1到多次
?    零次或者一次
{n}   出现n次
{n.}  出现n到多次
{n,m} 出现n到m次//=>2.特殊元字符:单个或者组合在一起代表特殊的含义
\       转义字符(普通->特殊->普通)
.       除\n(换行符)以外的任意字符
^       以哪一个元字符作为开始
$       以哪一个元字符作为结束
\n      换行符
\d      0~9之间的一个数字
\D      非0~9之间的一个数字
\w      数字、字母、下划线中的任意一个字符
\s      一个空白字符(包含空格、制表符、换页符等)
\t      一个制表符(一个TAB键:四个空格)
\b      匹配一个单词的边界
x|y     x或者y中的一个字符
[xyz]   x或者y或者z中的一个字符
[^xy]   除了x/y以外的任意字符
[a-z]   指定a-z这个范围的任意字符   [0-9a-zA-Z_]===\w
[^a-z]  上一个的取反“非”
()      正则中的分组符号
(?: )   只匹配不捕获
(?=)    正向预查
(?!)    负向预查//=>3.普通元字符:代表本身含义的
/wenlong/   此正则匹配的就是 “wenlong“
/*正则表达式常用的修饰符:img*/
i => ignoreCase 忽略单词的大小写匹配
m => mutiline   可以进行多行匹配
g => global     全局匹配/*
/A/.test('lalala')  //false
/A/i.test('lalala') //true
*/

元字符详细解析

^ $

let reg = /^\d/;
console.log(reg.test("wenlong")); //false
console.log(reg.test("2010wenlong")); //true
console.log(reg.test("wenlong2020")); //false
let reg = /\d$/;
console.log(reg.test("wenlong")); //false
console.log(reg.test("2010wenlong")); //false
console.log(reg.test("wenlong2020")); //true
//=>^/$ 两个都不加:字符串中包含符合规则的内容即可
let reg1 = /\d+/;
//=>^/$ 两个都加:字符串只能是和规则一致的内容
let reg2 = /^\d+$/;//=> 举个例子,手机号以1开头 只能包含11位数字
let reg = /^1\d{10}$/;

\

//=>.不是小数点,是除\n外的任意字符
let reg = /^2.3$/;
console.log(reg.test("2.3")); //true
console.log(reg.test("2@3")); //true
console.log(reg.test("23"));  //false//=>基于转义字符,让其只代表小数点
let reg = /^2\.3$/;
console.log(reg.test("2.3")); //true
console.log(reg.test("2@3")); //false
console.log(reg.test("23"));  //false//=>把特殊符号转为普通的
let str = "\d";
reg = /^\d$/;
console.log(reg.test(str)); //falsereg = /^\\d$/;
console.log(reg.test("\\d")); //true

x|y

//=>---直接x|y会存在很乱的优先级问题,一般我们写的时候都伴随小括号进行分组,因为小括号改变处理优先级
let reg = /^18|29$/;
console.log(reg.test("18"));   //true
console.log(reg.test("29"));   //true
console.log(reg.test("129"));  //true
console.log(reg.test("189"));  //true
console.log(reg.test("1829")); //true
console.log(reg.test("829"));  //true
console.log(reg.test("182"));  //truelet reg = /^(18|29)$/;  //只能是18或者29中的一个

[]

//=>1.中括号中出现的字符一般代表本身的含义
let reg = /^[@+]$/;
console.log(reg.test("@"));   //true
console.log(reg.test("+"));   //true
console.log(reg.test("@@"));  //false
console.log(reg.test("@+"));  //false//=>2. \d在中括号中还是0-9
reg = /^[\d]$/;
console.log(reg.test("d"));   //false
console.log(reg.test("\\"));  //false
console.log(reg.test("9"));   //truereg = /^[\\d]$/;
console.log(reg.test("d"));   //true
console.log(reg.test("\\"));  //true
console.log(reg.test("9"));   //false//=>3. 中括号中不存在多位数
reg=/^[18]$/;
console.log(reg.test("1"));   //true
console.log(reg.test("8"));   //true
console.log(reg.test("18"));  //falsereg=/^[10-29]$/;
console.log(reg.test("1"));   //true
console.log(reg.test("0"));   //true
console.log(reg.test("2"));   //true
console.log(reg.test("9"));   //true
console.log(reg.test("10"));  //false

常用的表达式

  1. 验证是否为有效数字
/*规则分析1.可能出现 + - 号,也肯能不出现2.一位0-9都可以,多位首位不能为03.小数部分可能有可能没有,一旦有后面必须有小数点+数字
*/
0
1
12
12.5
12.0
-1
-12.5
+9
09let reg = /^[+-]?(\d|([1-9]\d+))(\.\d+)?$/;  //简单正则
  1. 验证密码
let val = userPassInp.value;
//=>举个例子:不用正则
function checkPass(val){if(val.length<6 || val.length>16){alert('长度必须介于6-16位之间!');return;}let area = ['a','b',...,'_']; //包含数字、字母、下划线for(let i=0,i<val.length;i++){let char = val[i];if(!area.includes(char)){alert('格式不正确!');return;}}
}
//=>正则写法
let reg = /^\w{6,16}$/;
let flag = reg.test(val);
if(flag){alert('格式正确')}else{alert(‘格式不正确’);return;};
  1. 验证真实姓名的
/*
1.汉字 /^[\u4E00-\u9FA5]$/  中文第一个encode到最后一个
2.名字长度 2~10位
3.可能有译名  ·汉字exp:"弗拉基米尔·弗拉基米罗维奇·普京"
*/let reg = /^[\u4E00-\u9FA5]{2,10}(·[\u4E00-\u9FA5]{2,10}){0,2}$/;
  1. 验证邮箱的
let reg = /^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;
exp: abcd@qq.com.cn//=> \w+((-\w+)|(\.\w+))*
//1.开头是数字字母下划线(1到多位)
//2.还可以是 -数字字母下划线 或者 .数字字母下划线,整体零到多次
//邮箱的名字由“数字、字母、下划线、-、."几部分组成,但是-/.不能连续出现也不能作为开始//=> @[A-Za-z0-9]+
//1.@后面紧跟着:数字、字母 (1-多位)//=>((\.|-)[A-Za-z0-9]+)*
//对@后面名字的补充
//多域名 .com.cn
//企业邮箱 zxt@wenlong-xiaoxuan-office.com//=> \.[A-Za-z0-9]+
//1.这个匹配的是最后的域名(.com/.cn/.org/.edu/.net/.vip...)
  1. 身份证号码
/*
1.一共18位
2.最后一位可能是X身份证前六位:省市县    130130
中间八位:年月日    19920914
最后四位:最后一位  X或者数字倒数第二位  =>  偶数 女   奇数 男其余的都是经过算法算出来的
*///=>小括号分组的第二个作用:分组捕获,不仅可以把大正则匹配的信息捕获到,还可以捕获到每个小分组的内容
let reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|X)$/;
reg.exec("130828199012040617"); //=>["130828199012040617", "130828", "1990", "12", "04", "1", "7"...] 捕获结果是数组,包含每一个小分组单独获取的内容

正则两种创建方式的区别

//=>构造函数传的是字符串,\需要写两个才代表斜杠
let reg =/\d+/g;
reg = new RegExp("\\d+","g");//=>正则表达式中的部分内容是变量存储的值
//1.两个谢岗中间包起来的都是元字符(如果正则中要包含某个变量的值,则不能使用字面量方式创建)
let type = "wenlong";
reg = /^@"+type+"@$/;
console.log(reg.test("@wenlong@")); //=>false
console.log(reg.test('@""""typeeeeeee"@')); //=>true//2.这种情况只能使用构造函数方式(因为它传递的规则是字符串,只有这样才能进行字符串拼接)
reg = new RegExp("^@"+type+"@$");
console.log(reg.test("@wenlong@")); //=>true

正则的捕获

实现正则捕获的方法

  • 正则 RegExp.prototype 上的方法

    • exec
    • test
  • 字符串 String.ptototype 上支持正则表达式处理的方法
    • replace
    • match
    • splite
let str = "wenlong2019yangfan2020qihang2021";
let reg = /\d+/;
/*
基于exec实现正则的捕获1.捕获到的结果是null或者一个数组第一项:本次捕获到的其余项:对应小分组本次单独捕获的内容index:当前捕获内容在字符串中的起始索引input:原始字符串2.每执行一次,只能捕获到一个符合正则规则的即  正则捕获的懒惰性
*/
console.log(reg.test(str)); //=>true
console.log(reg.exec(str)); //=>["2019", index: 7, input: "wenlong2019yangfan2020qihang2021"]
console.log(reg.exec(str)); //=>["2019", index: 7, input: "wenlong2019yangfan2020qihang2021"]//=>解决捕获的懒惰性修改lastIndex:全局修饰符 exp:
let reg = /\d+/g;
console.log(reg.exec(str)); //=>["2019", index: 7, input: "wenlong2019yangfan2020qihang2021"]
console.log(reg.exec(str)); //=>["2020", index: 18, input: "wenlong2019yangfan2020qihang2021"]//=>实现正则捕获的前提是:当前正则要和字符串匹配,如果不匹配捕获的结果是null
let reg = /^\d+$/;
console.log(reg.test(str)); //=>false
console.log(reg.exec(str)); //=>null

正则捕获懒惰性的解决办法

~ function () {function execAll(str = "") {if (!this.global) return this.exec(str);let ary = [],res = this.exec(str);while (res) {ary.push(res[0]);res = this.exec(str);}return ary.length === 0 ? null : ary;}RegExp.prototype.execAll = execAll;
}();
let reg = /\d+/g;
let str = "wenlong2019yangfan2020qihang2021";
// 正则添加原型方法
console.log(reg.execAll(str));// 相当于字符串方法
console.log(str.match(reg))

正则的分组捕获

//=>身份证号码
let str = "130828199012040112";
let reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(?:\d|X)$/;
console.log(reg.exec(str));
console.log(str.match(reg));
//=>["130828199012040112", "130828", "1990", "12", "04", "1",, index: 0, input: "130828199012040112"]
/*
第一项:大正则匹配的结果
其余项:每一个小分组单独匹配捕获的结果
如果设置了分组(改变优先级),但是捕获的时候不需要单独捕获,可以基于?:来处理
*/
//=>既要捕获到{数字},也想单独的把数字也获取到,例如:第一次找到{0} 还需要单独获取0
let str = "{0}年{1}月{2}日";//=>不设置g匹配一次,exec和match获取的结果一致(既有大正则匹配的信息,也有小分组匹配的信息)
let reg = /\{(\d)+\}/;
console.log(reg.exec(str));
console.log(str.match(reg));
//=>["{0}", "0"]//=>
let reg = /\{(\d)+\}/g;
console.log(reg.exec(str));
console.log(str.match(reg)); //=>["{0}", "{1}", "{2}"] 多次匹配,match只能把大正则匹配的内容获取到,小分组匹配的信息无法获取let aryBig = [],arySmall = [],res = reg.exec(str);
while(res){let [big,small] = res;aryBig.push(big);arySmall.push(small);res=reg.exec(str);
}
console.log(aryBig,arySmall); //=>["{0}", "{1}", "{2}"] ["0", "1", "2"]
//=>分组引用
let str = "book"; //=>"good"、"look"、"moon"、"foot"...
let reg = /^[a-zA-Z]([a-zA-Z])\1[a-zA-Z]$/; //=>分组引用就是通过“\数字“让其代表和对应数组出现一模一样的内容
console.log(reg.test("book")); //=>true
console.log(reg.test("keep")); //=>true
console.log(reg.test("buss")); //=>false
console.log(reg.test("some")); //=>false

正则捕获的贪婪性

//=>默认情况下,正则捕获到的时候,是按照当前正则所匹配的最长结果来获取的
let str = "珠峰@2019#@2020培训";
let reg = /\d+/g;
console.log(str.match(reg)); //=>["2019","2020"]//=>在量词元字符后面设置? 取消捕获时候的贪婪性(按照匹配的最短的结果来获取)
let reg = /\d+?/g;
console.log(str.match(reg)); //=>["2", "0", "1", "9", "2", "0", "2", "0"]

问号在正则中的五大作用

  • 问号左边是非量词元字符:本身代表量词元字符,出现零到一次
  • 问号左边是量词元字符:取消捕获时候的贪婪性
  • (?: ) 只匹配不捕获
  • (?=) 正向预查
  • (?!) 负向预查

()三大作用

  • 改变优先级
  • 分组捕获
  • 分组引用

其它正则捕获的方法

  1. test 也能捕获(本意是匹配)
let str = "{0}年{1}月{2}日";
let reg = /\{(\d+)\}/g;
console.log(reg.test(str)); //=>true
console.log(RegExp.$1); //=>"0"console.log(reg.test(str)); //=>true
console.log(RegExp.$1); //=>"1"console.log(reg.test(str)); //=>true
console.log(RegExp.$1); //=>"2"console.log(reg.test(str)); //=>false
console.log(RegExp.$1); //=>"2" //=>"2" 存储的是上次捕获的结果//=>RegExp.$1~RegExp.$9:获取当前本次正则匹配后,第一个列到九个分组的信息
  1. replace 字符串实现替换的方法(一般都是伴随正则一起使用的)
let str = "wenlong@2019|wenlong@2020";
//=>把“wenlong”替换成“珠峰”
//1.不用正则,执行一次只能替换一个
str = str.replace("wenlong","珠峰").replace("wenlong","珠峰");
console.log(str);
//2.使用正则会简单一点
str = str.replace(/wenlong/g,"珠峰");
console.log(str);
let str = "wenlong@2019|wenlong@2020";
//=>把“wenlong"替换成“wenlongxiaoxuan";
str = str.replace("wenlong","wenlongxiaoxuan").replace("wenlong","wenlongxiaoxuan"); //=>"wenlongxiaoxuanxiaoxuan@2019|wenlong@2020"
//=>每一次替换都是字符串第一个位置开始找的(类似于正则捕获的懒惰性)//=>基于正则g可以实现
str = str.replace(/wenlong/g,"wenlongxiaoxuan");

案例:把时间字符串进行处理

let time = "2019-08-13";
//=>变为"2019年08月13日"
let reg = /^(\d{4})-(\d{1,2})-(\d{1,2})$/;//=>这样可以实现
time = time.replace(reg,"$1年$2月$3日");
console.log(time); //=>2019年08月13日//=>还可以这样处理[str].replace([reg],[fuction])
1.首先拿reg和time进行匹配捕获,能匹配到几次就会把传递的函数执行几次(而且是匹配一次就执行一次)
2.不仅把方法执行,而且replace还给方法传递了实参信息(和exec捕获的内容一致的信息:大正则匹配的内容,小分组匹配的信息。。。)
3.在函数中我们返回的是啥,就把当前大正则匹配的内容替换成啥time = time.replace(reg,(big,$1,$2,$3)=>{//=>这里的$1,$2,$3是我们自己设置的变量console.log(big,$1,$2,$3);
});time = time.replace(reg,(...arg)=>{let [,$1,$2,$3] = arg;$2.length<2?$2="0"+$2:null;$3.length<3?$3="0"+$3:null;return $1+"年"+$2+"月"+$3+"日";
})

单词首字母大写

let str = "good good study,day day up!"
let reg = /\b([a-zA-z])[a-zA-Z]*\b/g;
//=>函数被执行了六次,每一次都把正则匹配信息传递给函数
//=>每一次reg:["good","g"] ["good","g"] ["study","s"]...str = str.replace(reg,(...flag)=>{let [big,$1] = flag;console.log(flag,$1); //=> flag大正则匹配的内容,$1自定义小分组匹配的信息$1 = $1.toUpperCase();big = big.substring(1);return $1+big;
})

找出字符串中出现次数最多的值

//=>数组去重方式实现
let str = "wenlongxiaoxuanzhoulaoshi";
let obj = {};
[].forEach.call(str, char => {if (typeof obj[char] !== "undefined") {obj[char]++;return;}obj[char] = 1;
});
let max = 1,res = [];
for (let key in obj) {let item = obj[key];item > max ? max = item : null;
}
for (let key in obj) {let item = obj[key];if (item === max) {res.push(key);}
}
console.log(`出现次数最多的字符是:${res},出现了${max}次`);
//=>排序加正则方式实现
let str = "wenlongxiaoxuanzhoulaoshi";
str = str.split('').sort((a, b) => a.localeCompare(b)).join('');
let ary = str.match(/([a-zA-Z])\1+/g).sort((a, b) => b.length - a.length);
console.log(ary); //=>["hhh", "uuu", "ee", "ii", "nn", "oo"zz"]
let max = ary[0].length,res = [ary[0].substr(0, 1)];
for (let i = 1; i < ary.length; i++) {let item = ary[i];if (item.length < max) {break;}res.push(item.substr(0, 1));
}
console.log(`出现次数最多的字符是:${res},出现了${max}次`);

写到最后

本文章为个人正则学习记录,纯手打,转载请注明出处。

一小时学会js正则表达式相关推荐

  1. JS正则表达式完整版

    目录 引言 第一章 正则表达式字符匹配攻略 1 两种模糊匹配 2. 字符组 3. 量词 4. 多选分支 5. 案例分析 第1章 小结 第二章 正则表达式位置匹配攻略 1. 什么是位置呢? 2. 如何匹 ...

  2. JS正则表达式完整教程

    引言 亲爱的读者朋友,如果你点开了这篇文章,说明你对正则很感兴趣. 想必你也了解正则的重要性,在我看来正则表达式是衡量程序员水平的一个侧面标准. 关于正则表达式的教程,网上也有很多,相信你也看了一些. ...

  3. JS正则表达式完整教程(略长)

    注:本文已经整理成电子书:<JavaScript正则迷你书> 引言 亲爱的读者朋友,如果你点开了这篇文章,说明你对正则很感兴趣. 想必你也了解正则的重要性,在我看来正则表达式是衡量程序员水 ...

  4. 深入浅出Git教程+一个小时学会Git(转载)(堪称完美)

    转载自: https://www.cnblogs.com/best/p/7474442.html#!comments 目录 一个小时学会Git 一.版本控制概要 工作区 暂存区 本地仓库 远程仓库 1 ...

  5. 【JS-正则表达式】JS正则表达式完整教程(略长)

    引言 亲爱的读者朋友,如果你点开了这篇文章,说明你对正则很感兴趣. 想必你也了解正则的重要性,在我看来正则表达式是衡量程序员水平的一个侧面标准. 关于正则表达式的教程,网上也有很多,相信你也看了一些. ...

  6. 1小时学会:最简单的iOS直播推流(十一)spspps和AudioSpecificConfig介绍(完结)

    最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有,愿意懂直播技术的同学快来看!! 源 ...

  7. 1小时学会:最简单的iOS直播推流(十)librtmp使用介绍

    最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有,愿意懂直播技术的同学快来看!! 源 ...

  8. 1小时学会:最简单的iOS直播推流(八)h264/aac 软编码

    最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有,愿意懂直播技术的同学快来看!! 源 ...

  9. 1小时学会:最简单的iOS直播推流(七)h264/aac 硬编码

    最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有,愿意懂直播技术的同学快来看!! 源 ...

最新文章

  1. 北京大学计算机女博士经常看什么资料?
  2. 详解SQL中的触发器
  3. 如何优雅关闭 Spring Boot 应用
  4. @RestController/@Controller/@ResponseBody
  5. Hadoop的数据管理
  6. ruby中的复制 dup clone
  7. 比较 J2EE,eclipse adt扩展和Android studio几个类似IDE菜单的异同点
  8. Pure Pursuit trajectory tracking and Stanley trajectory tracking总结与比较
  9. win10配置SSH连接Github
  10. 毕业设计管理系统PHP,asp.net/net/c#毕业论文管理系统-成品
  11. RocketMQ报错 service not available now, maybe disk full, CL: 0.95 CQ: 0.95 INDEX: 0.95, maybe
  12. 使用idea导入文件夹作为项目时,在项目中的文件夹可能会被隐藏
  13. QImage对一般图像的处理
  14. 如何在Windows上安装Maven
  15. 6分钟速配 电商平台百万并发云压测实战
  16. mysql phpwind_Linux Apache php MySQL GD PHPWind 集成环境配置
  17. 原生JS路由实现页面跳转
  18. IDEA mybatis XML文件格式化问题
  19. Harbor docker login x509 certificate signed by unknown authority
  20. Ubuntu下解压rar压缩文件

热门文章

  1. SHOPYY建站平台推出免费CRM营销系统,20000封EDM邮件送不停!
  2. 大数据时代网络信息安全如何保障
  3. idea替换所有文件中的内容
  4. 常用javascript大全
  5. Linux磁盘的分区
  6. mac关闭nacos
  7. 【学术相关】写文献综述的28个要点
  8. Java调用支付宝支付接口
  9. 常用的脚手架有哪些?什么是软件开发脚手架?为什么需要脚手架?
  10. 四月三十号OCP考试失败了- -!