Appearance
JavaScript RegExp 对象
什么是正则表达式
正则表达式(Regular Expression,简称 RegExp)是一种用于匹配字符串中字符组合的模式。在 JavaScript 中,正则表达式也是对象。
正则表达式用于:
- 搜索字符串
- 替换字符串
- 提取字符串
- 验证字符串格式
正则表达式的创建
你可以通过以下两种方式创建正则表达式:
字面量语法
使用斜杠 (/) 包围模式:
javascript
// 字面量语法
let regex1 = /pattern/flags;
// 示例:匹配所有包含 "hello" 的字符串
let regex2 = /hello/;
// 示例:匹配所有包含 "hello" 的字符串,忽略大小写
let regex3 = /hello/i;构造函数语法
使用 RegExp 构造函数:
javascript
// 构造函数语法
let regex1 = new RegExp("pattern", "flags");
// 示例:匹配所有包含 "hello" 的字符串
let regex2 = new RegExp("hello");
// 示例:匹配所有包含 "hello" 的字符串,忽略大小写
let regex3 = new RegExp("hello", "i");
// 示例:使用变量作为模式
let pattern = "hello";
let regex4 = new RegExp(pattern);正则表达式的模式
字符类
| 模式 | 描述 |
|---|---|
[abc] | 匹配方括号内的任意一个字符 |
[^abc] | 匹配除了方括号内的任意一个字符 |
[a-z] | 匹配 a 到 z 范围内的任意一个字符 |
[A-Z] | 匹配 A 到 Z 范围内的任意一个字符 |
[0-9] | 匹配 0 到 9 范围内的任意一个数字 |
[a-zA-Z0-9] | 匹配字母和数字 |
元字符
| 元字符 | 描述 |
|---|---|
. | 匹配除换行符以外的任意单个字符 |
\d | 匹配一个数字字符,等价于 [0-9] |
\D | 匹配一个非数字字符,等价于 [^0-9] |
\w | 匹配一个字母、数字或下划线,等价于 [a-zA-Z0-9_] |
\W | 匹配一个非字母、数字或下划线,等价于 [^a-zA-Z0-9_] |
\s | 匹配一个空白字符(空格、制表符、换行符等) |
\S | 匹配一个非空白字符 |
\b | 匹配单词边界 |
\B | 匹配非单词边界 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
量词
| 量词 | 描述 |
|---|---|
* | 匹配前面的表达式 0 次或多次,等价于 {0,} |
+ | 匹配前面的表达式 1 次或多次,等价于 {1,} |
? | 匹配前面的表达式 0 次或 1 次,等价于 {0,1} |
{n} | 匹配前面的表达式恰好 n 次 |
{n,} | 匹配前面的表达式至少 n 次 |
{n,m} | 匹配前面的表达式至少 n 次,最多 m 次 |
分组和捕获
| 语法 | 描述 |
|---|---|
(x) | 捕获组,匹配 x 并记住匹配项 |
(?:x) | 非捕获组,匹配 x 但不记住匹配项 |
(?=x) | 正向先行断言,匹配后面跟着 x 的位置 |
(?!x) | 负向先行断言,匹配后面不跟着 x 的位置 |
标志
| 标志 | 描述 |
|---|---|
g | 全局匹配,查找所有匹配项 |
i | 忽略大小写 |
m | 多行匹配,使 ^ 和 $ 匹配每一行的开始和结束 |
s | 允许 . 匹配换行符 |
u | Unicode 模式,正确处理 Unicode 字符 |
y | 粘性匹配,从目标字符串的当前位置开始匹配 |
RegExp 对象的方法
1. test()
test() 方法用于测试字符串是否匹配正则表达式,返回布尔值。
javascript
let regex = /hello/;
console.log(regex.test("hello world")); // true
console.log(regex.test("hi world")); // false
// 使用全局标志
let regexGlobal = /hello/g;
console.log(regexGlobal.test("hello hello")); // true
console.log(regexGlobal.lastIndex); // 5(下一次匹配的开始位置)
console.log(regexGlobal.test("hello hello")); // true
console.log(regexGlobal.lastIndex); // 11
console.log(regexGlobal.test("hello hello")); // false(没有更多匹配项)
console.log(regexGlobal.lastIndex); // 0(重置为0)2. exec()
exec() 方法用于在字符串中执行正则表达式匹配,返回匹配结果数组或 null。
javascript
let regex = /hello/;
console.log(regex.exec("hello world")); // ['hello', index: 0, input: 'hello world', groups: undefined]
console.log(regex.exec("hi world")); // null
// 使用捕获组
let regexWithGroups = /(h)(e)(l)(l)(o)/;
console.log(regexWithGroups.exec("hello world"));
// ['hello', 'h', 'e', 'l', 'l', 'o', index: 0, input: 'hello world', groups: undefined]
// 使用全局标志
let regexGlobal = /hello/g;
console.log(regexGlobal.exec("hello hello")); // ['hello', index: 0, input: 'hello hello', groups: undefined]
console.log(regexGlobal.exec("hello hello")); // ['hello', index: 6, input: 'hello hello', groups: undefined]
console.log(regexGlobal.exec("hello hello")); // null字符串对象的正则方法
1. match()
match() 方法用于在字符串中执行正则表达式匹配,返回匹配结果数组或 null。
javascript
let str = "hello world";
let regex = /hello/;
console.log(str.match(regex)); // ['hello', index: 0, input: 'hello world', groups: undefined]
// 使用全局标志
let regexGlobal = /o/g;
console.log(str.match(regexGlobal)); // ['o', 'o']
// 使用捕获组
let str2 = "hello world";
let regexWithGroups = /(h)(e)(l)(l)(o)/;
console.log(str2.match(regexWithGroups));
// ['hello', 'h', 'e', 'l', 'l', 'o', index: 0, input: 'hello world', groups: undefined]2. replace()
replace() 方法用于在字符串中替换匹配的子串,返回替换后的新字符串。
javascript
let str = "hello world";
let regex = /hello/;
console.log(str.replace(regex, "hi")); // 'hi world'
// 使用全局标志
let str2 = "hello hello world";
let regexGlobal = /hello/g;
console.log(str2.replace(regexGlobal, "hi")); // 'hi hi world'
// 使用捕获组
let str3 = "John Doe";
let regexWithGroups = /(\w+) (\w+)/;
console.log(str3.replace(regexWithGroups, "$2, $1")); // 'Doe, John'
// 使用函数作为替换值
let str4 = "hello 123 world 456";
let regexNumbers = /\d+/g;
console.log(str4.replace(regexNumbers, (match) => parseInt(match) * 2)); // 'hello 246 world 912'3. search()
search() 方法用于在字符串中搜索匹配的子串,返回第一个匹配项的索引,未找到返回 -1。
javascript
let str = "hello world";
let regex = /world/;
console.log(str.search(regex)); // 6
let regex2 = /test/;
console.log(str.search(regex2)); // -14. split()
split() 方法用于将字符串分割为数组,返回分割后的数组。
javascript
let str = 'hello,world,test';
let regex = /,/;
console.log(str.split(regex)); // ['hello', 'world', 'test']
// 使用正则表达式分割
let str2 = 'hello world
test';
let regexWhitespace = /\s+/;
console.log(str2.split(regexWhitespace)); // ['hello', 'world', 'test']正则表达式的应用场景
1. 表单验证
javascript
// 验证邮箱
function validateEmail(email) {
const regex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
return regex.test(email);
}
console.log(validateEmail("test@example.com")); // true
console.log(validateEmail("invalid-email")); // false
// 验证手机号码
function validatePhone(phone) {
const regex = /^1[3-9]\d{9}$/;
return regex.test(phone);
}
console.log(validatePhone("13812345678")); // true
console.log(validatePhone("12345678901")); // false
// 验证密码强度
function validatePassword(password) {
// 至少8位,包含至少一个字母和一个数字
const regex = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/;
return regex.test(password);
}
console.log(validatePassword("Password123")); // true
console.log(validatePassword("password")); // false
console.log(validatePassword("12345678")); // false2. 字符串处理
javascript
// 提取URL中的域名
function extractDomain(url) {
const regex = /^(?:https?:\/\/)?(?:www\.)?([^\/]+)/i;
const match = url.match(regex);
return match ? match[1] : null;
}
console.log(extractDomain("https://www.example.com/path")); // 'example.com'
console.log(extractDomain("http://example.com")); // 'example.com'
console.log(extractDomain("example.com")); // 'example.com'
// 格式化日期
function formatDate(dateString) {
// 将 YYYY-MM-DD 格式转换为 DD/MM/YYYY
const regex = /^(\d{4})-(\d{2})-(\d{2})$/;
return dateString.replace(regex, "$3/$2/$1");
}
console.log(formatDate("2023-10-05")); // '05/10/2023'
// 移除HTML标签
function removeHtmlTags(html) {
const regex = /<[^>]+>/g;
return html.replace(regex, "");
}
console.log(removeHtmlTags("<p>Hello <b>world</b></p>")); // 'Hello world'3. 数据提取
javascript
// 提取文本中的所有数字
function extractNumbers(text) {
const regex = /\d+/g;
return text.match(regex) ? text.match(regex).map(Number) : [];
}
console.log(extractNumbers("There are 123 apples and 456 oranges.")); // [123, 456]
// 提取引号中的内容
function extractQuotedText(text) {
const regex = /"([^"]*)"/g;
const matches = [];
let match;
while ((match = regex.exec(text)) !== null) {
matches.push(match[1]);
}
return matches;
}
console.log(extractQuotedText('He said "hello" and she said "hi".')); // ['hello', 'hi']正则表达式的性能
性能优化技巧
避免过度使用正则表达式:对于简单的字符串操作,使用字符串方法(如
includes(),startsWith(),endsWith())可能比正则表达式更快。使用具体的模式:越具体的正则表达式模式,匹配速度越快。避免使用过于宽泛的模式,如
.*。使用非捕获组:对于不需要捕获的分组,使用非捕获组
(?:x)可以提高性能。避免回溯:复杂的正则表达式可能会导致大量回溯,影响性能。例如,避免使用
(a*)*b这样的模式。使用粘性标志
y:当你需要从特定位置开始匹配时,使用粘性标志y可以提高性能。缓存正则表达式:对于重复使用的正则表达式,将其存储在变量中,避免重复创建。
性能测试
javascript
// 测试字符串方法 vs 正则表达式
const text = "hello world";
// 测试 includes() 方法
console.time("includes");
for (let i = 0; i < 1000000; i++) {
text.includes("hello");
}
console.timeEnd("includes");
// 测试正则表达式 test() 方法
const regex = /hello/;
console.time("regex");
for (let i = 0; i < 1000000; i++) {
regex.test(text);
}
console.timeEnd("regex");最佳实践
选择合适的创建方式:
- 对于固定的模式,使用字面量语法
/pattern/ - 对于动态的模式,使用构造函数语法
new RegExp(pattern)
- 对于固定的模式,使用字面量语法
使用适当的标志:根据需要使用
g、i、m等标志。注意转义字符:在正则表达式中,某些字符具有特殊含义,需要使用反斜杠
\转义。处理全局标志的副作用:使用全局标志
g时,正则表达式对象会跟踪lastIndex属性,可能导致意外的行为。使用命名捕获组:ES2018 引入了命名捕获组,可以使代码更具可读性。
javascriptlet regex = /(?<firstName>\w+) (?<lastName>\w+)/; let match = regex.exec("John Doe"); console.log(match.groups.firstName); // 'John' console.log(match.groups.lastName); // 'Doe'使用正则表达式测试工具:使用在线工具(如 regex101.com)测试和调试正则表达式。
添加注释:对于复杂的正则表达式,添加注释说明其功能和各部分的含义。
javascript// 使用注释模式(需要 u 标志) let regex = /^\d{4}-\d{2}-\d{2}$/u; // 或者使用多行注释 let regexWithComments = new RegExp( "^" + // 字符串开始 "\\d{4}" + // 年(4位数字) "-" + // 分隔符 "\\d{2}" + // 月(2位数字) "-" + // 分隔符 "\\d{2}" + // 日(2位数字) "$" // 字符串结束 );
总结
RegExp 对象是 JavaScript 中处理字符串匹配和操作的强大工具。它提供了丰富的语法和方法来处理各种字符串模式匹配任务。了解正则表达式的语法和用法,有助于你更有效地处理 JavaScript 中的字符串操作。
通过合理使用正则表达式和遵循最佳实践,你可以编写更简洁、高效的 JavaScript 代码来处理各种字符串匹配和操作任务。