JavaScript 中的正则表达式(Regular Expression,简称 RegExp)是一种用于匹配字符串文本的强大工具。通过定义特定的模式,正则表达式可以有效地搜索、替换和验证字符串内容。JavaScript 中正则表达式的构造主要依靠
RegExp对象和一些内置的方法。在正则表达式中每匹配一段就在字符中消耗被匹配的内容 零宽断言除外。
使用示例
const text = "JavaScript is great!";
// 匹配单词 "JavaScript"
const regex = /javascript/i;
console.log(regex.test(text)); // true
// 提取所有单词
const words = text.match(/\b\w+\b/g); // \b 匹配空格 \w 匹配 英文字母 \b 匹配空格 g 搜索text全部字符,每匹配一次消耗 text 中的匹配字符,直到匹配完 text 全部字符
console.log(words); // ["JavaScript", "is", "great"]
// 替换 "great" 为 "awesome"
const newText = text.replace(/great/i, "awesome");
console.log(newText); // "JavaScript is awesome!"
创建正则表达式的方式
// 字面量方式:使用 /pattern/flags 的形式。
const regex = /hello/i; // 匹配 "hello",忽略大小写
// 构造函数方式:使用 RegExp 构造函数。
const regex = new RegExp("hello", "i"); // 匹配 "hello",忽略大小写
常用标志 就是 构造函数正则中的第二个参数,字面量正则中的最后一个字符
g:全局匹配,即查找所有匹配项。
i:忽略大小写。
m:多行匹配。
s:允许 . 匹配换行符(ES2018 引入)。
u:启用 Unicode 匹配模式(ES6 引入)。
y:粘性匹配,仅从正则表达式的 lastIndex 开始匹配(ES6 引入)。
常用正则表达式模式
.:匹配除换行符外的任意字符。
\d:匹配数字 [0-9]。
\D:匹配非数字。
\w:匹配字母、数字或下划线 [a-zA-Z0-9_]。
\W:匹配非字母、数字和下划线。
\s:匹配空白字符(包括空格、制表符等)。
\S:匹配非空白字符。
^:匹配字符串的开头。
$:匹配字符串的结尾。
字符组和分组
// 字符组:使用 [] 表示字符组,匹配其中任意一个字符。
const regex = /[aeiou]/; // 匹配任意元音字母
// 排除字符组:使用 [^] 表示不包含的字符组。
const regex = /[^aeiou]/; // 匹配非元音字母
// 分组:使用 () 进行分组,可以应用量词,也可以用于捕获匹配的子串。
const regex = /(ab)+/; // 匹配 "ab" 的重复
量词
*:匹配前面的字符 0 次或多次。
+:匹配前面的字符 1 次或多次。
?:匹配前面的字符 0 次或 1 次。
{n}:匹配前面的字符恰好 n 次。
{n,}:匹配前面的字符至少 n 次。
{n,m}:匹配前面的字符至少 n 次,至多 m 次。
常用方法
字符串方法:
str.match(regex):返回匹配结果数组。
str.replace(regex, replacement):替换匹配的子串。
str.search(regex):返回匹配的起始索引。
str.split(regex):根据匹配分割字符串。
RegExp 对象方法:
regex.test(str):测试字符串是否匹配正则表达式,返回 true 或 false。
regex.exec(str):执行匹配,返回第一个匹配项的信息。
零宽断言 又称正向前瞻 (?=...)
// `(?=...)` 确实是正则表达式中的**正向前瞻**(positive lookahead)断言,用于检查某个条件是否存在,而不消耗字符。它确保了在当前位置之后必须存在特定的模式。
const reg = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[A-Za-z\d]+$/ // 判断字符中必需包含 大小写字符,数字
const str1 = "Aa";
const str2 = "Aa2";
console.log(reg.test(str1)); // false 字符串不包含数字
console.log(reg.test(str2)); // true 字符中包含数字大小写字母
反向前瞻(Negative Lookbehind)(?<!...)
// **用法**:用于确保某个模式**不在当前位置之前**存在。
// **示例**:`(?<!abc)` 检查当前位置前面是否没有 `abc`。
const regex = /(?<!abc)def/;
const str1 = "abcdef";
// 不匹配,因为前面有abc
const str2 = "xyzdef";
// 匹配,因为前面没有abc
console.log(regex.test(str1)); // 输出: false
console.log(regex.test(str2)); // 输出: true
正向后顾(Positive Lookbehind)(?<=...)
// **用法**:用于确保某个模式**在当前位置之前**存在。
// **示例**:`(?<=abc)` 检查当前位置前面是否有 `abc`。
const regex = /(?<=abc)def/;
const str1 = "abcdef";
// 匹配,因为前面有abc
const str2 = "xyzdef";
// 不匹配,因为前面没有abc
console.log(regex.test(str1)); // 输出: true
console.log(regex.test(str2)); // 输出: false
只读组 (?:...)
// **用法**:与捕获组相似,但不保存匹配的内容。
// **示例**:`(?:abc)` 与 `(abc)` 相同,但不会捕获 这里的捕获是指 将使用()匹配内容。在使用特定api 例 match 时 会形成一个数组,里面的序列对应括号内容
const regex = /(?:abc)/;
const str = "abcdef";
console.log(regex.test(str)); // 输出: true
贪婪匹配与非贪婪匹配
正则表达式中的贪婪匹配(Greedy Matching)是指默认情况下,正则表达式会尽可能多地匹配字符。例如,正则表达式中的量词(如*、+、{m,n})默认都是贪婪的,它们会尝试匹配尽可能多的字符,直到不满足条件为止。
- 在贪婪模式下,
.*会尽量匹配尽可能多的字符,因此a.*c会匹配整个字符串aabac,即.*会匹配ab。 - 如果想要使正则表达式非贪婪匹配(也叫惰性匹配),可以在量词后加上
?,使其尽可能少地匹配字符。例如,a.*?c:
// 贪婪匹配 例中 .* 尽可能的匹配多了字符 将需要 test 截断的字符也匹配了
console.log(/this(.*)test/.exec("this is test test test reg")) // [ "this is test test test", " is test test " ]
// 非贪婪匹配 .* 尽可能少的匹配,判断了 test 当匹配到 test 就没有继续捕获内容了
console.log(/this(.*?)test/.exec("this is test test test reg")) // [ "this is test", " is " ]