JavaScript 正则表达式完全指南
面向编程小白的RegExp对象知识点汇总 – 通俗易懂的解释和实用示例
🔍 什么是正则表达式?
正则表达式(Regular Expression,简称Regex或RegExp)是用于匹配字符串中字符组合的模式。
👨🏫 通俗解释:正则表达式就像是一个”字符串模板”,你可以用这个模板来查找、匹配或替换文本内容。
在JavaScript中,正则表达式有两种创建方式:
字面量方式(推荐):
const regex = /pattern/flags;
构造函数方式:
const regex = new RegExp('pattern', 'flags');
💡 两种方式的区别:字面量方式在脚本加载时编译,构造函数方式在运行时编译。当你需要动态构建正则表达式时,使用构造函数方式。
🔤 基本元字符
元字符是正则表达式中具有特殊含义的字符:
元字符 | 含义 | 示例 |
---|---|---|
. |
匹配任意单个字符(除了换行符) | /a.c/ 匹配 “abc”, “aac” |
^ |
匹配字符串的开始 | /^Hello/ 匹配以”Hello”开头的字符串 |
$ |
匹配字符串的结束 | /world$/ 匹配以”world”结尾的字符串 |
\d |
匹配任意数字(等价于[0-9]) | /\d\d/ 匹配两个连续数字 |
\w |
匹配字母、数字或下划线 | /\w+/ 匹配一个或多个单词字符 |
\s |
匹配空白字符(空格、制表符等) | /hello\s+world/ 匹配”hello”和”world”之间有空格 |
❗ 注意:如果要匹配元字符本身,需要在前面加上反斜杠\
进行转义。例如:\.
表示匹配点号。
🔢 量词(匹配次数)
量词指定匹配前面模式的次数:
量词 | 含义 | 示例 |
---|---|---|
* |
匹配前一项0次或多次 | /bo*/ 匹配 “b”, “bo”, “booo” |
+ |
匹配前一项1次或多次 | /a+/ 匹配 “a”, “aa”, 但不匹配空 |
? |
匹配前一项0次或1次 | /colou?r/ 匹配 “color” 或 “colour” |
{n} |
匹配前一项恰好n次 | /\d{3}/ 匹配三个连续数字 |
{n,} |
匹配前项至少n次 | /\d{2,}/ 匹配至少两个连续数字 |
{n,m} |
匹配前项n到m次 | /\d{2,4}/ 匹配2到4个连续数字 |
⚠️ 默认情况下,量词是”贪婪匹配” – 它们会尽可能多地匹配字符。在量词后添加?
可使其变为”非贪婪匹配”(懒惰匹配)。
贪婪匹配 vs 非贪婪匹配:
// 贪婪匹配
const greedy = /<.+>/.exec('<div>Hello</div>')[0]; // 匹配整个字符串
// 非贪婪匹配
const lazy = /<.+?>/.exec('<div>Hello</div>')[0]; // 只匹配 <div>
🚩 标志(Flags)
标志用于改变正则表达式的匹配行为:
标志 | 含义 | 描述 |
---|---|---|
g |
全局匹配 | 查找所有匹配而非在第一个匹配后停止 |
i |
忽略大小写 | 匹配时不区分大小写 |
m |
多行模式 | 使 ^ 和 $ 匹配每行的开始和结束 |
s |
dotAll模式 | 允许 . 匹配换行符 |
u |
Unicode模式 | 正确处理大于\uFFFF的Unicode字符 |
y |
粘性匹配 | 从目标字符串的当前位置开始匹配 |
标志使用示例:
// 全局匹配 + 忽略大小写
const regex = /hello/gi;
// 多行模式示例
const multiLine = /^line/gm;
const str = "line one\nline two";
str.match(multiLine); // 匹配["line", "line"]
🛠️ RegExp对象方法
RegExp对象提供了两个主要方法:
test()
– 测试字符串是否匹配正则表达式
const regex = /hello/;
regex.test('hello world'); // true
regex.test('goodbye'); // false
exec()
– 执行搜索匹配,返回详细匹配信息数组
const regex = /h(ell)o/;
const result = regex.exec('hello world');
// result: ["hello", "ell", index: 0, input: "hello world"]
exec()
方法返回的数组包含以下属性:
[0]
: 完整匹配的字符串[1]...[n]
: 捕获组匹配的内容index
: 匹配到的字符起始位置input
: 原始输入字符串
🧵 字符串的正则方法
String对象提供了几个使用正则表达式的方法:
方法 | 描述 | 示例 |
---|---|---|
match() |
检索匹配结果,返回匹配数组或null | 'hello'.match(/h(ell)o/) |
matchAll() |
返回匹配的所有结果(ES2020) | [...'a1b2'.matchAll(/\d/g)] |
search() |
返回匹配的第一个索引,未找到返回-1 | 'hello'.search(/ell/) // 1 |
replace() |
替换匹配的子字符串 | '2023'.replace(/\d/g, 'x') // "xxxx" |
split() |
使用正则分隔字符串 | 'a,b, c'.split(/\s*,\s*/) // ["a","b","c"] |
💡 在replace()
方法中,可以使用$1, $2
等引用捕获组:
const result = 'John Doe'.replace(/(\w+)\s(\w+)/, '$2, $1');
// result: "Doe, John"
👥 分组和捕获
分组允许你将多个字符组合为一个单元,使用圆括号()
实现:
捕获组:
const regex = /(\d{4})-(\d{2})-(\d{2})/;
const result = regex.exec('2023-10-25');
// result[1] = "2023"
// result[2] = "10"
// result[3] = "25"
非捕获组(?:...)
– 只分组不捕获:
const regex = /(?:Mr|Ms|Mrs)\. (\w+)/;
const result = regex.exec('Mr. Smith');
// result[0]: "Mr. Smith"
// result[1]: "Smith" (没有捕获称谓)
命名捕获组(?<name>...)
– 给捕获组命名(ES2018):
const regex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const result = regex.exec('2023-10-25');
console.log(result.groups.year); // "2023"
console.log(result.groups.month); // "10"
📋 常用正则表达式示例
一些实用的正则表达式例子:
用途 | 正则表达式 |
---|---|
电子邮箱 | /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/ |
URL | /(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/ |
手机号 | /^1[3-9]\d{9}$/ |
身份证号 | /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])\d{3}[0-9Xx]$/ |
HTML标签 | /<([a-z]+)([^<]+)*(?:>(.*?)<\/\1>|[^>]*\/>)/gi |
⚠️ 注意:在实际应用中,复杂的验证(如身份证号)通常需要结合后端验证,正则只能验证格式。
🎯 正则表达式测试器
测试文本:
Hello, this is a test string with 123 numbers and some punctuation! 你好,世界!
匹配结果将显示在这里…