「这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战」。
正则表达式
1 . 什么是正则表达式
正则表达式( Regular Expression )是 : 对字符串进行匹配运算的内置对象
- (1) 表达式 : 对字符串进行逻辑匹配运算
- (2) 内置对象 : js语言提供好的内置对象,存储一些对字符串进行匹配运算的方法。
2 . 正则表达式作用
对字符串进行逻辑匹配运算( 格式校验 )
3.正则表达式使用流程
(1) 声明正则对象 :
- 语法 :
let reg = new RegExp( /正则表达式/ )(2) 调用对象 test 方法 : - 语法 :
reg.test( '要校验的字符串' )- true : 符合规则
- false : 不符合规则
//(1)声明正则对象
let reg = new RegExp(/a/)
//(2)调用正则对象test方法
console.log( reg.test('wfsfsfsf') ) // false 没有a
console.log( reg.test('wfsafsfsf') ) // true 有a
正则表达式字面量写法
有一些内置对象有字面量写法
- 数组:
new Array():[] - 对象:
new Object():{} - 正则:
new RegExp(/正则/):/正则/
console.log( /a/.test('xdgbdfgd') ) // false 没有a
4 . 正则表达式语法组成
正则表达式语法由两部分组成
1 . 原义文本字符
字符串本身的含义
- PS : 别多想,写什么就是什么。想的越多,错的越离谱
- 示例 :
/掘金/: 含义检测字符串中有没有掘金- PS : 不是检测有掘, 也不是去检测有金, 也不是去检测既有掘又有金,就是检测字符串有没有掘金而已
console.log(/掘金/.test('掘土的人'))//false
console.log(/掘金/.test('找金子的人'))//false
console.log(/掘金/.test('掘了金子的人'))//false
console.log(/掘金/.test('掘金前端程序员'))//true
- 示例2 :
/abc/: 含义检测字符串有没有abc
console.log( /abc/.test('a123') )//false
console.log( /abc/.test('a1b23') )//false
console.log( /abc/.test('a1b2c3') )//false
console.log( /abc/.test('123abc') )//true
2 . 元字符
改变了字符串本身的含义, 类似于js中的关键字
- 元字符包含有
[]: 字符类[^]: 反向类[0-9]: 范围类. \ |: 预定义类^ $: 边界{}+ ? *: 量词(): 分组g i m: 修饰符
5 . 元字符 - 字符类
[] 字符类 : 将某种特征的字符归为一类。
/[abc]/: 将 a 或 b 或 c 这种字符归为一类- 直意思为 : 检测字符串有没有 a 或 b 或 c
console.log(/[abc]/.test('a123'))//true
console.log(/[abc]/.test('a123b123'))//true
console.log(/[abc]/.test('a123b123c123'))//true
console.log(/[abc]/.test('abcabc'))//true
console.log(/[abc]/.test('123123'))//false
6 . 元字符 - 反向类
[^] 反向类 : 将不是某种特征的字符归为一类。
/[^abc]/: 将不是a 或 不是b 或 不是c的字符归为一类- 直意思为 : 检测字符串有没有 不是 a 或 b 或 c 的任意一个字符
console.log(/[^abc]/.test('a123'))//true
console.log(/[^abc]/.test('a123b123'))//true
console.log(/[^abc]/.test('a123b123c123'))//true
console.log(/[^abc]/.test('abcabc'))//false
console.log(/[^abc]/.test('123123'))//true
7 . 元字符 - 范围类
范围类应用场景 :
- 需求1 :检测字符串中有没有数字字符
/[0123456789]/: 检测有没有数字字符
- 需求2 :检测字符串中有没有字母
/[abcdefghijklmnopqrstuvwxyz]/: 这种正则很冗余
- 解决办法 : 这种正则很冗余,而范围类就好的解决了问题
范围类 : 代表字符类的范围
/[0-9]/: 检测有没有数字字符/[a-z]/: 检测有没有小写字母/[A-Z]/: 检测有没有大写字母
范围类注意点 :
- (1) 范围类可以连写
/[a-zA-Z0-9]/: 检测字符串有没有字母或数字
- (2) 范围类是一个闭区间
/[5-8]/: 检测有没有 5-8 之间的数据。 包含 5 和 8
- (3)范围类 右边 一定大于 左边
/[8-5]/: 直接报错。 范围类一定是右边大于左边/[8-90-5]/: 可以的 。 包含 8 9 0 1 2 3 4 5
console.log( /[0-9]/.test('abc123') )//true
console.log( /[a-z]/.test('abc123') )//true
console.log( /[A-Z]/.test('abc123') )//false
//检测 8-5范围 : 8 9 0 1 2 3 4 5
console.log( /[8-90-5]/.test('abc123') )//true
8 . 元字符 - 预定义类
- 什么是预定义类 : 正则表达式提供好的用来匹配常见的字符类
- 预定义类的等价类含义 :
-
预定义类 :
.类含义 :[^\r\n]除了回车和换行之外的所有字符 -
预定义类 :
\d类含义 :[0-9]数字字符外的 -
预定义类 :
\D类含义 :[^0-9]非数字字符 -
预定义类 :
\s类含义 :[\f\n\r\t\v]空白字符 -
预定义类 :
\S类含义 :[^\f\n\r\t\v]非空白字符 -
预定义类 :
\w类含义 :[a-zA-Z_0-9]单词字符(字母、下划线、数字) -
预定义类 :
\W类含义 :[^a-zA-Z_0-9]非单词字符
-
// /./ : 除了回车和换行之外的所有字符
console.log(/./.test(' asf ')) //true
console.log(/./.test('\n')) //false
// \d : 相当于[0-9],任意数字
console.log(/\d/.test('abcabc'))//false
console.log(/\d/.test('abc123'))//true
// \D : 相当于[^0-9],非数字字符
console.log(/\D/.test('abcabc'))//true
console.log(/\D/.test('abc123'))//true
// \s : 空白字符
console.log(/\s/.test('abc abc'))//true
// \S : 非空白字符
console.log(/\S/.test('abc abc'))//true
// \w : 单词字符(a-zA-Z0-9_)
console.log(/\w/.test('+-*/'))//false
9 . 元字符 - 边界
边界: 正则表达式提供了几个常用的边界匹配字符
边界字符及其含义 :
^: 以xxxx开头$: 以xxxx结束\b: 单词边界\B: 非单词边界
1. 开头边界
以 xxx 开头
/^abc/- 正确含义: 以a(开头) + bc(a的后面一定要是bc)
- 错误含义: 以abc开头 (虽然这个正则表面上必须是前面是abc的才符合,但是这个正则就不能理解为以abc开头)
console.log(/^abc/.test('a123abcabc')) //false
console.log(/^abc/.test('a1b1c1')) //false
console.log(/^abc/.test('abcabc')) //true
2. 结尾边界
以xxx结尾
/abc$/- 正确含义 : ab + c(c结尾位置,前面是ab)
- 错误含义 : 以abc结尾(虽然这个正则表面上必须是abc在结尾位置才符合,但是这个正则就不能理解为以abc结尾)
console.log(/abc$/.test('ab123c')) //false
console.log(/abc$/.test('abc123')) //false
console.log(/abc$/.test('abcabc')) //true
3.正则严格匹配
同时添加开头边界与结尾边界 /^abc$/
- 正确含义 : a(开头) + b + c(结尾)
- 世界上只有唯一的一个字符满足条件: abc
- 错误含义 : 以abc开头 且 以abc结尾的字符
console.log(/^abc$/.test('a123abcabc')) //false
console.log(/^abc$/.test('ab123c')) //false
console.log(/^abc$/.test('abc123')) //false
console.log(/^abc$/.test('abcabc')) //false
console.log(/^abc$/.test('abc')) //true
实例场景 : /^[0-9]$/ 检测 (开头)数字(结尾)
- 说人话 :检测一个字符串是不是一个数字
- 只有: 0 1 2 3 4 5 6 7 8 9符合
- 错误解读 : 字符串开头是数字,结尾也是数字
console.log(/^[0-9]$/.test('123'))//false
console.log(/^[0-9]$/.test('789'))//false
console.log(/^[0-9]$/.test('123abc123'))//false
4 . 单词边界
需求 : 替换 'This is a body' 中 'is' 为 'X' 得到 'This X a body'
console.log( 'This is a body'.replace(/is/,'X')) // ThX is a body
- 此时不能完成替换想要的 'is'
- 使用单词边界
/\bis/检测 'is' 是不是一个独立的单词
console.log( 'This is a body'.replace(/\bis/,'X'))// This X a body
5 . 元字符 - 量词
为什么要有量词
- 需求 : 检测一个字符串有没有11个数字
/\d\d\d\d\d\d\d\d\d\d\d/: 检测字符串中有连续的 11 个数字 量词作用 : 检测字符出现的次数?: 出现零次或一次(最多出现一次 <=1)+: 出现一次或多次(至少出现一次 >=1)*: 出现零次或多次(任意次){n}: 出现n次{n,m}: 出现n-m次{n,}: 出现至少n次(>=n)
// /\d?/ : 匹配 零次或一次(最多出现一次 <=1)
console.log('1234567890abc'.replace(/\d?/,'X'))// X234567890abc
console.log('a1234567890abc'.replace(/\d?/,'X'))// Xa1234567890abc
// /\d+/ : 匹配 出现一次或多次(至少出现一次 >=1)
console.log('1234567890abc'.replace(/\d+/,'X'))// Xabc
console.log('a1234567890abc'.replace(/\d+/,'X'))// aXabc
// /\d*/ : 匹配 出现零次或多次(任意次)
console.log('1234567890abc'.replace(/\d*/,'X'))// Xabc
console.log('a1234567890abc'.replace(/\d*/,'X'))// Xa1234567890abc
// /\d{5}/ : 匹配5次
console.log('1234567890abc'.replace(/\d{5}/,'X'))// X67890abc
// /\d{5,8}/ : 匹配5-8次
console.log('1234567890abc'.replace(/\d{5,8}/,'X'))// X90abc
// /\d{5,}/ : 匹配>=5次
console.log('1234567890abc'.replace(/\d{5,}/,'X'))// Xabc
10 . 元字符 - 分组
() 在正则中有三种含义
- 分组 : 把多个字符归为一组,用于量词
- 提升优先级 : 让 | 只匹配小括号内部的字符,提升|的优先级
- 反向引用(提取) : 正则会提取()内部匹配的数据存入$中,可以进行反向引用
1. 分组()
把多个字符归为一组,用于量词
/love{3}/: 含义 匹配 lov + e(3次)- 默认情况下量词只能对 一个 字符生效
/(love){3}/: 含义 匹配 (love) 三次- 如果希望量词可以对 多个字符生效,就可以使用()将多个字符归为一组
2. 提升优先级 ()
/lo|ive/: 含义 匹配 有 lo 或 ive|: 正则中|代表或的意思,对|两边所有的字符生效
/l(o|i)ve/: 含义 匹配l + o|i ve()和|一起使用可以提升 | 的优先级
console.log(/lo|ive/.test('lo123')) //true
console.log(/lo|ive/.test('ive123')) //true
console.log(/lo|ive/.test('love123')) //true
console.log(/l(o|i)ve/.test('lo123')) //false
console.log(/l(o|i)ve/.test('ive123')) //false
console.log(/l(o|i)ve/.test('love123')) //true
3.反向引用 :
- 正则表达式在匹配的时候,会自动把
()内部匹配到的数据提取到RegExp的$变量中。($1-$9) - 此时可以可以在替换字符串的时候,通过调整
$的顺序对字符串进行反向引用(调整字符串格式顺序)
console.log('2021-11-21'.replace(/(\d{4})-(\d{2})-(\d{2})/, '$3/$2/$1'))//21/11/2021
console.log(RegExp.$1)//2021
console.log(RegExp.$2)//11
console.log(RegExp.$3)//21
反向引用的应用场景 : 日期转换
- 大陆: 年-月-日 2021-11-21
- 香港: 日/月/年 21/11/2021
11 . 元字符 - 修饰符
修饰符 : 对正则表达式进行修饰作用,可以改变正则表达式结果
g: global , 全局匹配i: intensity , 区分大小写m: multiple , 检测换行符。用于边界 修饰符语法 :/正则表达式/修饰符
g : 全局匹配
/a/ : 匹配字符a
- 默认情况下,正则只能匹配第一个
console.log('a123A456aaa789AAA'.replace(/a/,'X'))// X123A456aaa789AAA
- 如果希望正则可以匹配所有的,就可以使用 g 修饰符
console.log('a123A456aaa789AAA'.replace(/a/g,'X'))// X123A456XXX789AAA
i : 不区分大小写
- 默认情况下,正则表达式区分大小写
console.log('a123A456aaa789AAA'.replace(/A/,'X'))// a123X456aaa789AAA
- 如果希望正则不区分大小写,就可以使用 i修饰符
console.log('a123A456aaa789AAA'.replace(/A/i,'X'))// X123A456aaa789AAA
m : 检测换行符。 需要和边界在一起使用
m 含义 : 让边界 对换行符生效。 换行符后面的内容视为边界
let str = '我爱我的掘金\n我爱我的掘金\n我爱我的掘金'
console.log( str.replace(/^我/gm,'掘金') )
console.log( str.replace(/(.+)我(.+)/gm,'$1掘金$2') )//替换中间的我
12 . 正则表达式注意点
- 正则表达式修饰符是可以同时写多个的
console.log('a123A456aaa789AAA'.replace(/A/ig,'X'))// X123X456XXX789XXX
- 正则表达式元字符含义可能不止一种,会有多种含义。 (类似于js的 + )
/abc/: 原义文本字符。 检测字符串有没有abc/[abc]/: 字符类。 检测字符串是否有 a或b或c 其中之一。/[^abc]/: 反向类。 检测字符串是否有 不是a或 不是b或 不是c 任意字符。^写在[]里面就是反向类/^abc/: 开头边界。 检测字符串是不是a开头^单独使用就是开头边界。 边界不是检测字符串,而是检测位置的。