小白学-正则

251 阅读6分钟

什么是正则

正则是一种搜索和替换字符串的一种强大的工具,正则表达式(可叫做‘regexp’或者‘reg'),其中包含了模式修饰符

怎么创建正则和基本使用

创建正则表达式对象有两种语法, 一种是通过构造函数,new操作符创建,它允许从字符串中动态地构造模式, 当正则表达式会改变时,或者事先不知道什么模式,就可以使用构造函数来创建

let reg = new RegExp('冰冰')// 创建正则 第一个''里面是条件
console.log('我的心是王冰冰的'.search(reg))// 5 返回冰冰的下标

另一种是字面量的方法,通过斜杠‘/’创建,斜杠‘/’会告诉js我们正在创建一个正则, 当我们知道用什么模式,并且不会改变时,可以采用字面量的方法创建

let reg=/冰冰/ // 创建正则,'/条件/'斜杆中间放置的是条件
console.log('我的心是王冰冰的'.search(reg)) //5 返回冰冰的下标

特殊字符 字符类

上面的两个简单的小🌰是精准的匹配,我们知道是谁,可以创建,但是有些时候,我们匹配的是一个不确定的字符但是知道是什么类型的时候怎么办,比如我们来寻找冰冰的手机号,'王冰冰的手机号是:18888888888',这时候我要获取'18888888888',这个时候就该特殊字符出马了,我们知道手机号是数字0-9,那么我们就可以用\d来获取数字了,

let reg=/\d/ // 创建正则,
console.log('王冰冰的手机号是:18888888888'.match(reg)) 
//["1", index: 9, input: "王冰冰的手机号是:18888888888", groups: undefined] 
// 我们看到第一项输出['1']  这个是我们的匹配的结果
// index 代表结果的下标
// input 代表我们输入的是什么
// groups 代表组的名称

但是呢,这时候我们发现了为嘛结果只有一个"1",这不是我们想要的啊,'18888888888'才是我们要的,别急我们\d是获取一个,我们要获取多个只需\d+就可以啦

let reg=/\d+/ // 创建正则,
console.log('王冰冰的手机号是:18888888888'.match(reg)) 
// ["18888888888", index: 9, input: "王冰冰的手机号是:18888888888", groups: undefined]
特殊字符作用
d匹配0-9的数字等价于[0-9]
D匹配一个非数字字符
w匹配一个单字字符(字母、数字、下划线)等价于[a-zA-Z0-9_]
W匹配一个非单字字符除了(字母、数字、下划线等价于)[^a-zA-Z0-9_]
s匹配一个空白字符,包括空格、制表符、换页符、换行符
S匹配一个非空白字符
\在非特殊字符之前的反斜杠表示下一个字符是特殊字符,不能按照字面理解,在不是特殊字符前表示是转义字符 \\表示是一个\
表示匹配输入的开始,/^A/ 并不会匹配 "an A" 中的 'A',但是会匹配 "An E" 中的 'A'。
$表示匹配输入的结束,/t$/ 并不会匹配 "eater" 中的 't',但是会匹配 "eat" 中的 't'。
*匹配前一个表达式的0次或多次
+匹配前一个表达式的1次或多次
?匹配前一个表达式的0次或1次,/e?le?/ 匹配 "angel" 中的 'el'、"angle" 中的 'le' 以及 "oslo' 中的 'l',如果紧跟在任何量词 、 +、? 或 {} 的后面*,将会使量词变为非贪婪**(匹配尽量少的字符),和缺省使用的贪婪模式(匹配尽可能多的字符)正好相反。例如,对 "123abc" 使用 /\d+/ 将会匹配 "123",而使用 /\d+?/ 则只会匹配到 "1"
.匹配除了换行符以外的所有的单个字符
let reg=/^a?\d+$/ // 创建正则,可以以字母a开头,以数字结尾
console.log('a18888888888'.match(reg)) 
// ["a18888888888", index:0, input: "a18888888888", groups: undefined]
console.log('18888888888'.match(reg)) 
// ["18888888888", index: 0, input: "18888888888", groups: undefined]
// 匹配一个qq邮箱
let email = '199999999@qq.com'
let reg = /^\d+@\w+\.com$/;
console.log(email.match(reg));// ["199999999@qq.com"]

特殊字符 符号类

在上面的qq邮箱示例中,如果不是com结尾而是cn结尾的呢,这时候该怎么匹配,这时可以用| 表示或者

// 匹配一个qq邮箱
let email = "199999999@qq.com";
let email2 = "199999999@qq.cn";
let email3 = "199999999@qq.com.cn";
let reg = /^\d+@\w+(\.\w+)+\1?/;
let reg1 = /^\d+@\w+\.(com|cn)$/;
console.log(email.match(reg1)); // ["199999999@qq.com", ".com"]
console.log(email2.match(reg)); // ["199999999@qq.cn", ".cn"]
console.log(email3.match(reg)); // ["199999999@qq.com.cn", ".cn"]
特殊字符作用
|x|y 匹配‘x’或者‘y’。
()(x)捕获括号 它会匹配 'x' 并且记住匹配项,在/(f)(b)\1\2/中\1表示f,\2表示b,在正则表达式替换中可以使用$1来表示原字符串
{n}n是一个正整数,匹配前一个字符出现了几次
{n,}n是一个正整数,匹配前一个字符最少出现了几次
{n,m}n 和 m 都是整数。匹配前面的字符至少n次,最多m次。如果 n 或者 m 的值是0, 这个值被忽略
[xyz]字符的集合,匹配[]中的任意一项,可以用-来选一个范围[0-9]
[^xyz]字符的集合,它匹配任何没有包含在方括号中的字符
// 匹配一个手机号,宽松超级 13,15,17,18开头的十一位数字
let tel = "18787875678";
let tel1 = "12787875678";
let reg = /^1[3,5,7,8]\d{9}$/;
console.log(tel.match(reg)); //["18787875678"]
console.log(tel1.match(reg)); //null
// 匹配一个座机号 前面四位数字-链接 后面跟着7到8位数字
let tel = "0100-89087678";
let tel1 = "010-89087678";
let reg = /^\d{3,4}-\d{7,8}$/;
console.log(tel.match(reg)); //["0100-89087678"]
console.log(tel1.match(reg)); //["010-89087678"]

方法

上面我们一直用的是match方法,它返回一个数组,在未匹配到时会返回 null。其实还有其它的方法

方法描述
exec执行查找匹配的RegExp方法,它返回一个数组(未匹配到则返回 null)。
test一个在字符串中测试是否匹配的RegExp方法,它返回 true 或 false。
match一个在字符串中执行查找匹配的String方法,它返回一个数组,在未匹配到时会返回 null。
matchAll一个在字符串中执行查找所有匹配的String方法,它返回一个迭代器(iterator
search一个在字符串中测试匹配的String方法,返回匹配的位置,没有则返回-1
replace一个在字符串中执行查找匹配的String方法,并且使用替换字符替换匹配的
split一个使用正则表达式或者一个固定字符串分隔一个字符串,并将分隔后的子字符串存储到数组中的 String 方法
let tel = "0100-89087678";
let tel1 = "010-89087678";
let reg = /^\d{3,4}-\d{7,8}$/;
console.log(reg.exec(tel1)); // ["0100-89087678"]
console.log(reg.test(tel)); //true
console.log(tel.match(reg)); // ["0100-89087678"]
console.log(tel.search(reg)); //0
console.log(
tel.replace(reg, function () {
return "*".repeat(10);
})
); //**********

高级搜索

正则表达式有六个可选参数 (flags) 允许全局和不分大小写搜索等。这些参数既可以单独使用也能以任意顺序一起使用, 并且被包含在正则表达式实例中。

方法描述
g全局搜索
i不区分大小写
m多行匹配
s允许.匹配换行符
u使用unicode码的模式进行匹配。
y执行“粘性(sticky)”搜索,匹配从目标字符串的当前位置开始
let str = "This this this";
let reg1 = /t/i; // 匹配t不区分大小写
let reg2 = /t/g; // 全局匹配t
let reg3 = /t/gi;  // 全局匹配t不区分大小写
console.log(str.match(reg1)); // ['T']
console.log(str.match(reg2)); // ["t", "t"]
console.log(str.match(reg3)); // ["T", "t", "t"]
    

断言查找

方法描述
x(?=y)匹配'x'仅仅当后面跟着‘y’,这种叫做先行断言
(?<=x)y匹配'x'仅仅当前面有‘y’,这种叫做后行断言
x(?!y)匹配'x'仅仅当后面不跟着‘y’,这种叫做正向否定查找
(?<!x)y匹配'x'仅仅当前面没有‘y’,这种叫做反向否定查找
// 隐藏手机号
let tel = "18787875678";
let reg = /(?<=\w{3})\w+(?=\w{4})/; 
tel.replace(reg, () => {
  return "*".repeat(4);
});
// "187****5678"