正则表达式是一种用来匹配和处理文本的强大工具,它可以用在很多编程语言和文本编辑器中。本文将详细总结正则表达式的基本语法和常用的元字符、量词、分组、断言、修饰符等概念,以及一些实用的正则表达式示例。
正则表达式的基本语法
正则表达式是由一系列的字符组成的,其中一些字符有特殊的含义,称为元字符。元字符可以表示一类字符、一个位置、一个重复次数或一个逻辑关系等。下面是一些常用的元字符:
.
表示任意一个字符,除了换行符和回车符
let str = 'baidu';
var patt = /./g;
console.log(str.match(patt));
// ['b', 'a', 'i', 'd', 'u']
[]
表示一个字符集合,可以匹配其中任意一个字符,例如 [abc] 可以匹配 a、b 或 c
let str = 'google';
var patt = /[ge]/g;
console.log(str.match(patt));
// ['g', 'g', 'e']
[^]
表示一个反向字符集合,可以匹配不在其中的任意一个字符,例如 [^abc] 可以匹配除了 a、b 和 c 之外的任意字符
let str = 'foreval.cn';
var patt = /[^vo]/g;
console.log(str.match(patt));
// ['f', 'r', 'e', 'a', 'l', '.', 'c', 'n']
-
表示一个范围,可以用在字符集合中,例如 [a-z] 可以匹配任意一个小写字母;[A-Z]可以匹配任意一个大写字母
let str = 'foreval.cn';
var patt = /[a-z]/g;
console.log(str.match(patt));
// ['f', 'o', 'r', 'e', 'v', 'a', 'l', 'c', 'n']
^
表示字符串的开始,例如 ^abc 只能匹配以 abc 开头的字符串
let arr = ['foreval','baidu','google','foreach'];
var patt = /^for/g;
arr.forEach(item => console.log(item.match(patt)));
// ['for'], null, null, ['for']
$
表示字符串的结束,例如 abc$ 只能匹配以 abc 结尾的字符串
let arr = ['foreval','baidu','google','foreach'];
var patt = /eval$/g;
arr.forEach(item => console.log(item.match(patt)));
// ['eval'], null, null, null
|
表示或者,可以用来连接两个子表达式,表示匹配其中任意一个,例如 abc|def 可以匹配 abc 或 def
let str = 'foreval.cn';
var patt = /for|l/g;
console.log(str.match(patt));
// ['for', 'l']
()
表示分组,可以用来将一部分正则表达式作为一个整体,例如 (abc)+ 可以匹配 abc 的一次或多次重复
let str = 'foreval.cn,forEach';
var patt = /(for)+/g;
console.log(str.match(patt));
// ['for', 'for']
\
表示转义,可以用来取消元字符的特殊含义,或者表示一些特殊字符,例如 . 可以匹配 . 字符本身,而 \n 可以匹配换行符
let str = 'foreval.cn, ,forEach';
var patt = /\s/g;
console.log(str.match(patt));
// [' ']
正则表达式的常用量词
量词是用来表示一个字符或者一个分组重复出现的次数的。下面是一些常用的量词:
*
表示零次或多次,相当于 {0,},例如 a* 可以匹配空字符串或者 a 的任意次重复
let str = 'abacad';
console.log(str.match(/a*/g,''))
// ['a', '', 'a', '', 'a', '', '']
+
表示一次或多次,相当于 {1,},例如 a+ 可以匹配 a 的一次或多次重复
let str = 'abacad';
console.log(str.match(/a+/g,''))
// ['a', 'a', 'a']
?
表示零次或一次,相当于 {0,1},例如 a? 可以匹配空字符串或者 a 字符
let str = 'abacad';
console.log(str.match(/[a]?/g,''))
// ['a', '', 'a', '', 'a', '', '']
{n}
表示恰好 n 次,例如 a{3} 只能匹配 aaa
let str = `abbcccdddd`
let reg = /[d]{2}/g;
console.log(str.match(reg))
// ['dd', 'dd']
{n,}
表示至少 n 次,例如 a{3,} 可以匹配 aaa 或更多个 a
let str = `abbcccdddd`
let reg1 = /[d]{2,}/g;
let reg2 = /[d]{4,}/g;
let reg3 = /[d]{6,}/g;
console.log(str.match(reg1)) // ['dddd']
console.log(str.match(reg2)) // ['dddd']
console.log(str.match(reg3)) // null
{n,m}
表示至少 n 次,至多 m 次,例如 a{3,5} 可以匹配 aaa、aaaa 或 aaaaa
let str = `abbcccdddd`
let reg = /[d]{2,3}/g;
console.log(str.match(reg)) // ['ddd']
量词默认是贪婪的,也就是说会尽可能多地匹配字符。如果要让量词变成非贪婪的,可以在量词后面加上一个 ? 符号。例如 a+? 可以匹配 a 的最少重复次数。
正则表达式的常用分组
分组是用来将一部分正则表达式作为一个整体的,可以对分组应用量词或者断言等操作。分组有以下几种类型:
普通分组
普通分组又称为捕获组,用 () 表示,例如 (abc)+ 可以匹配 abc 的一次或多次重复
捕获组的作用是什么呢?它会把括号里面的正则表达式匹配到的内容存储到该分组里面,也就是说,它捕获的就是分组里面的正则表达式匹配到的内容。最简单的捕获组是(),但是它匹配的是一个空字符(即字符之前的位置)。
非捕获分组
非捕获分组,用 (?: ) 表示,表示不需要保存分组的匹配结果,例如 (?:abc)+ 也可以匹配 abc 的一次或多次重复,既然是非捕获组,则不会保存匹配结果
命名分组
命名分组,用 (?
后向引用分组
后向引用分组,用 \n 表示,表示引用前面第 n 个分组的匹配结果,例如 (abc)\1 可以匹配 abcabc
正向预查分组
正向预查分组,用 (?=) 表示,表示匹配后面跟着的表达式,但不包含在结果中,例如 abc(?=def) 可以匹配 abcdef 中的 abc,但不包含 def
负向预查分组
负向预查分组,用 (?!) 表示,表示匹配后面不跟着的表达式,但不包含在结果中,例如 abc(?!def) 可以匹配 abcd 中的 abc,但不包含 d
正向回顾分组
正向回顾分组,用 (?<=) 表示,表示匹配前面是的表达式,但不包含在结果中,例如 (?<=abc)def 可以匹配 abcdef 中的 def,但不包含 abc
负向回顾分组
负向回顾分组,用 (?<!) 表示,表示匹配前面不是的表达式,但不包含在结果中,例如 (?<!abc)def 可以匹配 bdef 中的 def,但不包含 b
正则表达式的常用断言
断言是用来表示一个位置或者一个条件的。下面是一些常用的断言:
-
^ 表示字符串的开始
-
$ 表示字符串的结束
-
\b 表示单词边界
-
\B 表示非单词边界
-
(?=) 表示正向预查
-
(?!) 表示负向预查
-
(?<=) 表示正向回顾
-
(?<!) 表示负向回顾
正则表达式的常用修饰符
修饰符是用来修改正则表达式的行为和特性的。下面是一些常用的修饰符:
-
i 表示忽略大小写
-
g 表示全局匹配
-
m 表示多行模式
-
s 表示单行模式
-
x 表示忽略空白字符和注释
修饰符可以单独使用或者组合使用。不同的编程语言和文本编辑器可能支持不同的修饰符。
正则表达式的实用示例
下面给出一些实用的正则表达式示例:
- 匹配邮箱地址:/\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*/
let str = 'foreval@163.com';
let reg = /\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/g;
console.log(str.match(reg))
// ['foreval@163.com']
- 匹配手机号码:/^(0|86|17951)?(13[0-9]|15[012356789]|166|17[3678]|18[0-9]|14[57])[0-9]{8}$/
let str = '17866668888';
let reg = /^(0|86|17951)?(13[0-9]|15[012356789]|166|17[3678]|18[0-9]|14[57])[0-9]{8}$/g;
console.log(str.match(reg))
// ['17866668888']
- 匹配身份证号码:/([1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3})|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[Xx]))$/
let str = '100071199902091234';
let reg = /(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[Xx])$)/g;
console.log(str.match(reg))
// ['100071199902091234']
- 匹配网址:/^https?😕/(([a-zA-Z0-9_-])+(.)?)(:\d+)?(/((.)?(?)?=?&?a-zA-Z0-9_-?))*$/i
let str1 = 'https://foreval.cn';
let str2 = 'http://foreval.cn';
let reg = /^https?:\/\/(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?(\/((\.)?(\?)?=?&?[a-zA-Z0-9_-](\?)?)*)*$/ig;
console.log(str1.match(reg))
console.log(str2.match(reg))
// ['https://foreval.cn']
// ['http://foreval.cn']
- 匹配 IP 地址:(\d{1,3}.){3}\d
let str = '192.168.0.1';
let reg = /^(\d{1,3}.){3}\d$/g;
console.log(str.match(reg))
// ['192.168.0.1']
- 匹配 HTML 标签:<[^>]+>
let str = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
</html>`
let reg = /<[^>]+>/g;
console.log(str.match(reg))
// ['<!DOCTYPE html>', '<html lang="en">', '<head>', '<meta charset="UTF-8">', '<meta name="viewport" content="width=device-width, initial-scale=1.0">', '<title>', '</title>', '</head>', '<body>', '</body>', '</html>']
- 匹配中文字符:[\u4e00-\u9fa5]
let str = `鹅鹅鹅,曲项向天歌。abc123`
let reg = /[\u4e00-\u9fa5]/gm;
console.log(str.match(reg))
// ['鹅', '鹅', '鹅', '曲', '项', '向', '天', '歌']
- 将字符串中的相邻重复出现的字符匹配出来
// 比如将字符串aaabbbbcccccddd中重复出现的aaa、bbbbb、ccccc、ddd这种重复两次以上的字符串匹配出来
let str = 'aaabbbbcccccddd';
let reg = /(.)\1+/g;
console.log(str.match(reg))
// ['aaa', 'bbbb', 'ccccc', 'ddd']
往期精彩:
3、ref和reactive到底哪个更好?vue3中两种响应式数据的优缺点对比
评论区