💻【JavaScript】正则表达式🏠专栏:JavaScript
👀个人主页:繁星学编程🍁
🧑个人简介:一个不断提高自我的平凡人🚀
🔊分享方向:目前主攻前端,其他知识也会阶段性分享🍀
👊格言:☀️没有走不通的路,只有不敢走的人!☀️
👉让我们一起进步,一起成为更好的自己!!!🎁
文章目录
【JavaScript】正则表达式
正则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE)使用单个字符串来描述、匹配一系列符合某个句法规则的字符串搜索模式。
一. 什么是正则表达式?
正则表达式是由一个字符序列形成的搜索模式。
当你在文本中搜索数据时,你可以用搜索模式来描述你要查询的内容。
正则表达式可以是一个简单的字符,或一个更复杂的模式。
正则表达式可用于所有文本搜索和文本替换的操作。
二. 创建正则表达式
(1) 内置构造函数方式创建
语法:
let 变量 = new RegExp("正则表达式","修饰符");
参数:
- 正则表达式:可以是字符串或者变量
- 修饰符:可以是全局匹配(g)、忽略大小写(i)、多行匹配(m)
// eg: 判断字符串(abCDcs)中是否有(abcd),并且全局匹配(g)、忽略大小写(i)
let reg = new RegExp('abcd', 'ig');
console.log(reg.test('abCDcs')); // true
(2) 字面量方式创建
语法:
let 变量 = /正则表达式/修饰符
注:使用字面量创建的正则表达式只能是字符串
// eg:
let reg = /abcd/ig;
console.log(reg.test('abCDcs')); // true
三. 正则表达式修饰符
修饰符 可以在全局搜索中不区分大小写:
i(ignore case):忽略大小写
g(global):执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)
m(multiple lines):执行多行匹配
设置匹配模式时,可以都不设置,也可以设置1个,也可以全设置,设置时没有顺序要求。
四. 正则表达式的方法
(一) 正则对象的方法
(1) test()
概念:用于检测一个字符串是否匹配某个模式,如果字符串中含有匹配的文本,则返回 true,否则返回 false。
语法:正则表达式.test(字符串)
返回值:返回一个布尔值,如果字符串中含有匹配的文本,则返回 true,否则返回 false。
let a = new RegExp("e");// 检查下列句子中是否含有e
document.write(a.test("There is a good thing"));
<!-- 结果:true -->
(2) exec()
概念:在一个指定字符串中执行一个搜索匹配。返回一个结果数组或 null。
语法:正则表达式.exec(字符串)
返回值:把字符串中符合正则要求的第一项以及一些其他信息,以数组的形式返回
注:该方法是将字符串中满足正则表达式的部分提取出来
let reg = /\d[a-z]/;
let str = "ab56efg";
let res = reg.exec(str);
console.log(res);
// ['6e', index: 3, input: 'ab56efg', groups: undefined]
/*
返回值中的第一项:匹配的值('6e')
第二项:匹配的索引,只找第一个(index: 3)
第三项:匹配的字符串(input: 'ab56efg')
第四项:分组(这里没有所以,groups: undefined)(可以忽略)
*/
//遇到满足条件的就返回,所以只返回5
(二) 字符串支持的正则方法
(1) split()
概念:将一个字符串拆分为一个数组
语法:字符串.split(正则表达式/字符串)
返回值:返回被拆分后的数组
let str = "1j1j1k2d7o";
console.log(str.split("k")); // ['1j1j1', '2d7o']
let result = str.split(/[A-z]/);
console.log(result); // ['1', '1', '1', '2', '7', '']
(2) replace()
概念:用于在字符串中用一些字符串替换另一些字符串,或替换一个与正则表达式匹配的子串。
语法:字符串.replace(换下字符串,换上字符串)
注:第二参数可以是字符串也可以是回调函数
// eg: 使用正则表达式且不区分大小写将字符串中的 Cat 替换为 Root
var str = "Visit Cat !";
var txt = str.replace(/cat/i,"Root");
结果输出为:Visit Root !
// eg: 批量替换敏感词
var arr = ['HH', 'MM', 'NN']
var str = 'aHHdfasMMdfaNNdsfaNNsNNdffas'
var reg = new RegExp(arr.join("|"), "g")
console.log(str.replace(reg, '**')); // a**dfas**dfa**dsfa**s**dffas
(3) match()
概念:检索返回一个字符串匹配正则表达式的结果。
语法:字符串.match(正则表达式)
返回值:以数组的格式返回满足条件的第一项
var reg=/[a-z]/g;
var str="ab56efg";
var res=str.match(reg); //字符串中满足表达式的部分提取出来
console.log(res);//结果:['a', 'b', 'e', 'f', 'g']
match() 和exec()的同异点
区别:
- exec()方法是:正则表达式提供的方法
- match()方法是:字符串的方法
相同: 都返回一个数组,只要匹配到符合规则的数据就返回
(4) search()
search() 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串,并$\color{red} {返回子串的起始位置} $。
语法:字符串.search(正则表达式)
返回值:找到目标值返回对应的索引,没找到返回-1
.
// eg:使用正则表达式搜索 "Root" 字符串,且不区分大小写
var str = "Visit Root!";
var n = str.search(/Root/i);
console.log(n); // 6
五. 正则表达式模式
(1) 方括号
方括号用于查找某个范围内的字符:
表达式 | 描述 |
---|---|
[abc] | 查找方括号之间的任何字符。 |
[0-9] | 查找任何从 0 至 9 的数字。 |
(x|y) | 查找任何以 | 分隔的选项。 |
// eg: 匹配数字字母中的任意一个字符
[a-zA-Z0-9]
(2) 元字符
元字符(Metacharacter)是拥有特殊含义的字符:
元字符 | 描述 |
---|---|
. | (小数点)默认匹配除换行符之外的任何单个字符。 |
\w | 匹配一个单字字符(字母、数字或者下划线)。等价于 [A-Za-z0-9_] 。 |
\W | 匹配一个非单字字符。等价于 [^A-Za-z0-9_] 。 |
\d | 查找数字(至少含有一个数字(0~9)) |
\D | 查找非数字字符(至少含有一个非数字) |
\s | 查找空白字符(至少含有一个空白字符(空格、缩进、\b…)) |
\S | 查找非空白字符(至少含有一个不是空白字符) |
\b | 匹配单词边界 |
\B | 匹配非单词边界 |
\0 | 查找NUL字符 |
\n | 查找换行符 |
\f | 查找换页符 |
\r | 查找回车符 |
\t | 查找制表符 |
\v | 查找垂直制表符 |
\xxx | 查找以八进制 xxx 规定的字符 |
\xdd | 查找以十六进制 dd 规定的字符 |
\uxxxx | 查找以十六进制 xxxx 规定的 Unicode 字符 |
实例
var reg = /\W/ //true
console.log(reg.test("!@#!"))
var reg = /\D/ //false
console.log(reg.test("123"))
var reg = /\bchild\b/ //false
console.log(reg.test("hello children"))
(3) 量词
量词 | 描述 |
---|---|
? | 出现0次或一次 |
+ | 出现一次或多次 |
* | 出现0次或多次 |
{n} | 出现n次 |
{n,m} | 出现n到m次 |
{n,} | 至少出现n次 |
实例
var reg = /a{3}/;//判断a是否连续出现3次
console.log(reg.test("aaabc"));//true
console.log(reg.test("abc"));//false
var reg = /(ab){3}/;//判断ab是否连续出现3次
console.log(reg.test("abababc"));//true
console.log(reg.test("abc"));//false
var reg = /ab{1,3}c/;//判断b是否连续出现1-3次
console.log(reg.test("abbbc"));//true
console.log(reg.test("abbbbbc"));//false
console.log(reg.test("bac"));//false
(4) 正则语法
正则 | 描述 |
---|---|
| | 或 |
[ ] | 或 |
[^ ] | 除了 |
[a-z] | 小写字母 |
[A-Z] | 大写字母 |
[A-z] | 任意字母 |
^ | 开头 |
$ | 结尾 |
实例:
//检查字符串中是否含有a或b
var reg = /a|b/
console.log(reg.test("bcd"))//结果:true
//检查字符串中是否含有字母
var reg = /[a-z]/
console.log(reg.test("bcdfsji"))//结果:true
//检查字符串中是否含有abd或abc或abf
var reg = /ab[cdf]/
console.log(reg.test("bcabcji"))//结果:true
//检查一个字符串是否以a结尾
var reg = /a$/
console.log(reg.test("bcabcjia"))//结果:true
//如果在正则表达式中同时使用^ $则要求必须完全符合正则表达式
var reg = /^a$/
console.log(reg.test("as"))//结果:false
(5) 重复元字符
符号: \数字
作用: 表示重复第n个小括号的内容,要求和第n个小括号的内容一模一样
// 表示这个()里面的整体内容出现2次就可以。不要求一模一样
// var reg1 = /^(abc|def){2}$/
// 表示 \1 位置 需要出现一个 和 第一个 小括号 一模一样的内容
var reg1 = /^(abc|def)\1$/
console.log(reg.test('abcabc')); // true
console.log(reg.test('defdef')); // true
console.log(reg.test('abcdef')); // false
var reg2 = /^(abc|def)(哈哈|嘻嘻)\2$/
console.log(reg.test('abc哈哈哈哈')); // true
console.log(reg.test('abc哈哈嘻嘻')); // false
console.log(reg.test('abc嘻嘻嘻嘻')); // true
(6) 正则的捕获方式
语法:正则表达式.exec(字符串)
作用:始字符串中捕获到符合正则规则的字符串片段
返回值:
-
当原始字符串没有符合规则的时候,返回null
-
当原始字符串由符合规则的片段的时候:
返回值必然是一个数组,数组的[0] 是捕获出来的字符串片段
-
没有(), 没有g
不管写多少次,只能捕获第一组匹配规则的字符串片段
var reg = /\d{3}/ var str = 'adfa123sals456hdfl789kasakhdf012' var res = reg.exec(str) console.log(res); // ['123', index: 4, input: 'adfa123sals456hdfl789kasakhdf012', groups: undefined] console.log(reg.exec(str)); // ['123', index: 4, input: 'adfa123sals456hdfl789kasakhdf012', groups: undefined] console.log(reg.exec(str)); // ['123', index: 4, input: 'adfa123sals456hdfl789kasakhdf012', groups: undefined]
-
有()
会在返回值数组的[1]开始,依次是每一个()中单独的内容
var reg = /(\d{2})(\d{2})(\d{2})(\d{4})(\d{2})(\d{2})(\d{2})(\d)(\d|x)/ var str = '22230120050101123x' console.log(reg.exec(str)); // ['22230120050101123x', '22', '23', '01', '2005', '01', '01', '12', '3', 'x', index: 0, input: '22230120050101123x', groups: undefined]
-
有g
g 叫做全局标识符
第二次捕获开始会从第一次捕获的结束为止开始检索
直到找不到内容,返回null
var reg = /\d{3}/g var str = 'adfa123sals456hdfl789kasakhdf012' console.log(reg.exec(str)); // ['123', index: 4, input: 'adfa123sals456hdfl789kasakhdf012', groups: undefined] console.log(reg.exec(str)); // ['456', index: 11, input: 'adfa123sals456hdfl789kasakhdf012', groups: undefined] console.log(reg.exec(str)); // ['789', index: 18, input: 'adfa123sals456hdfl789kasakhdf012', groups: undefined]
-
匹配但是不捕获
当我们需要使用()这个整体作用,但是不需要把()里面的内容单独捕获的时候:可以书写( ?: )
六. 正则的两大特性
-
懒惰
每次捕获的时候都会从字符串[0]开始检索
解决:给正则添加标识符g,(查找所有匹配而非在找到第一个匹配后停止) -
贪婪
每次在捕获内容的时候,尽可能多的去捕获内容
解决:使用非贪婪限定符(在原来的限定符后面加一个?)
// 贪婪捕获
let str = '1234567abcd'
let reg = /\d*/
console.log(reg.exec(str)); // ['1234567', index: 0, input: '1234567abcd', groups: undefined]
贪婪限定符:(*、+、?、{n,}、{n,m})
// 贪婪限定符
let reg = /<div.*>/
console.log(reg.exec(str)); // '<div class="box" id="box"><span></span></div>'
非贪婪限定符:(*?、+?、??、{n,}?、{n,m}?)
// 非贪婪限定符
let reg = /<div.*?>/
console.log(reg.exec(str)); // '<div class="box" id="box">'
七. ES9新特性(正则扩展)
(1) 命名捕获分组
捕获:对正则匹配的数据进行(.*)单独提取。
// 声明一个字符串
let str = '<a href="http://www.baidu.com">你好</a>';
// 需求:提取url和标签内文本
// 之前的写法
const reg = /<a href="(.*)">(.*)<\/a>/;
const result = reg.exec(str);
console.log(result);
// 结果是一个数组,第一个元素是所匹配的所有字符串
// 第二个元素是第一个(.*)匹配到的字符串
// 第三个元素是第二个(.*)匹配到的字符串
// 我们将此称之为捕获
console.log(result[1]); // http://www.baidu.com
console.log(result[2]); // 你好
// 使用命名捕获分组的写法:
const reg1 = /<a href="(?<url>.*)">(?<text>.*)<\/a>/;
const result1 = reg1.exec(str);
console.log(result1);
// 这里的结果多了一个groups
// groups:
// text:"你好"
// url:"http://www.baidu.com"
console.log(result1.groups.url); // http://www.baidu.com
console.log(result1.groups.text); // 你好
结果:
(2) 反向断言
断言:判断这次的匹配结果是否正确
正向断言/反向断言 做一个唯一性的识别
正向断言(目标的后面)
let str = "JS314你知道么5呀";
// 需求:我们只想匹配到5
// 正向断言
const reg = /\d+(?=呀)/;
const result = reg.exec(str); // ['5', index: 9, input: 'JS314你知道么5呀', groups: undefined]
结果:
反向断言(目标的前面)
let str = "JS314你知道么5呀";
// 反向断言
const reg1 = /(?<=么)\d+/;
const result1 = reg1.exec(str);
console.log(result1); // ['5', index: 9, input: 'JS314你知道么5呀', groups: undefined]
结果:
(3) dotAll 模式
dot就是. 元字符,表示除换行符之外的任意单个字符
之前的写法:
let str = `
<ul>
<li>
<a href="#">a</a>
<p>b</p>
</li>
<li>
<a href="#">c</a>
<p>d</p>
</li>
</ul>
`;
const reg = /<li>\s+<a href="#">(.*?)<\/a>\s+<p>(.*?)<\/p>/;
console.log(reg.exec(str));
结果:
使用dotAll后:
let str = `
<ul>
<li>
<a href="#">a</a>
<p>b</p>
</li>
<li>
<a href="#">c</a>
<p>d</p>
</li>
</ul>
`;
// const reg = /<li>\s+<a href="#">(.*?)<\/a>\s+<p>(.*?)<\/p>/g;
const reg = /<li>.*?<a href="#">(.*?)<\/a>.*?<p>(.*?)<\/p>/gs;
// console.log(reg.exec(str));
let result;
while ((result = reg.exec(str))) console.log(result);
g为全局匹配 匹配不到是返回null,结束循环
结果:
八. 案例
案例一:书写正则验证用户名
规则:
- 6 ~ 12 位
- 只能包含数字字母下划线 \w
- 不能以 下划线开头
var reg = /^[0-9a-zA-Z]\w{5,11}$/
案例二:书写正则验证邮箱
规则:
- @ 前面, 和用户名规则一致
- 邮箱类型只接受 163 qq sina
- 后缀只接受 com cn
var reg = /^[0-9a-zA-Z]\w{5,11}@(163|qq|sina)\.(com|cn)$/
案例三:书写正则验证手机号
规则:
- 前面有可能带有 +86 有可能没有 ? {0,1}
- +86 和 电话号之间有可能有空格有可能没有
- 号段只接受 133 135 188
var reg = /^(\+86 ?)?(133|135|188)\d{8}$/
案例四:书写正则验证 0 ~ 255 的数字
var reg = /^(\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])$/
<!-- 验证:0 ~ 666 -->
var reg = /^(\d{1,2}|[1-5]\d{2}|6[0-5]\d|66[0-6])$/
案例五:连字符和驼峰之间的转换
// 连字符转驼峰
let str = 'get-element-by-id';
let res = str.replace(/-[a-z]/g, function (result) {
return result.slice(1).toUpperCase();
})
console.log(res); // getElementById
// 驼峰转连字符
let str = 'getElementById'
let res = str.replace(/[A-Z]/g, function (result) {
return '-' + result.slice(0).toLowerCase();
})
console.log(res); // get-element-by-id
案例六:封装函数实现字符串首尾空格
function reTrim(str) {
// 首先判断是不是一个字符串
if (!typeof str === 'string') return;
return str.replace(/^\s+|\s+$/g, '');
}
console.log(reTrim(str));
案例七:敏感词替换
// eg: 批量替换敏感词
var arr = ['HH', 'MM', 'NN']
var str = 'aHHdfasMMdfaNNdsfaNNsNNdffas'
var reg = new RegExp(arr.join("|"), "g")
console.log(str.replace(reg, '**')); // a**dfas**dfa**dsfa**s**dffas
结束语:
希望对您有一点点帮助,如有错误欢迎小伙伴指正。
👍点赞:您的赞赏是我前进的动力!
⭐收藏:您的支持我是创作的源泉!
✍评论:您的建议是我改进的良药!
一起加油!!!💪💪💪