JavaScript 正则表达式
在本教程中,您将了解正则表达式的工作原理,以及如何使用它们在 JavaScript 中高效地执行模式匹配。
什么是正则表达式
正则表达式,通常称为"regex"或"RegExp",是一种特殊格式的文本字符串,用于在文本中查找模式。 正则表达式是当今最强大的工具之一,可用于有效和高效的文本处理和操作。 例如,可用于验证用户输入的姓名、电子邮件、电话号码等数据的格式是否正确,在文本内容中查找或替换匹配的字符串等。
JavaScript 支持 Perl 风格的正则表达式。 为什么使用 Perl 风格的正则表达式? 因为 Perl(Practical Extraction and Report Language)是第一个为正则表达式提供集成支持的主流编程语言,并且以其对正则表达式的强大支持以及非凡的文本处理和操作能力而闻名。
在深入研究正则表达式之前,让我们先简要概述一下用于执行模式匹配的常用 JavaScript 内置方法。
函数 | 它的作用 |
---|---|
exec() |
在字符串中搜索匹配项。 它返回一个信息数组或在不匹配时返回 null 。 |
test() |
测试字符串是否匹配模式。 它返回 true 或 false 。 |
search() |
在字符串中搜索匹配项。 它返回第一个匹配的索引,如果没有找到,则返回 -1 。 |
replace() |
在字符串中搜索匹配,并将匹配的子字符串替换为替换字符串。 |
match() |
在字符串中搜索匹配项。 它返回一个信息数组或在不匹配时返回 null 。 |
split() |
使用正则表达式将字符串拆分为子字符串数组。 |
注意: 方法 exec()
和 test()
是 RegExp 方法,以字符串为参数,而方法 search()
, replace()
, match()
和 split()
是字符串方法,以正则表达式为参数。
定义正则表达式
在 JavaScript 中,正则表达式由 RegExp 对象表示,它是一个原生的 JavaScript 对象,如 String、Array 等。 有两种方法可以创建新的 RegExp 对象 — 一种是使用文字语法,另一种是使用 RegExp()
构造函数。
文字语法使用正斜杠 (/pattern/
) 包裹正则表达式模式,而构造函数语法使用引号 ("pattern"
)。 下面的示例演示了创建匹配任何以"Mr."开头的字符串的正则表达式的两种方法。
// Literal syntax
var regex = /^Mr\./;
// Constructor syntax
var regex = new RegExp("^Mr\\.");
如您所见,正则表达式文字语法更短且更易于阅读。 因此,最好使用文字语法。 我们还将在本教程中使用它。
注意: 在使用构造函数语法时,你必须对 a href="#special-characters">特殊字符 进行双转义,这意味着匹配"."。 你需要写 "\\."
而不是 "\."
。 如果只有一个反斜杠,它将被 JavaScript 的字符串解析器解释为转义字符并被删除。
使用正则表达式进行模式匹配
正则表达式模式包括使用字母、数字、标点符号等,加上一组特殊的正则表达式字符(不要与 HTML 特殊字符)。
在正则表达式中被赋予特殊含义的字符是: .
*
?
+
[
]
(
)
{
}
^
$
|
\
。 每当您想按字面意思使用这些字符时,都需要反斜杠。 例如,如果要匹配".",则必须编写 \.
。 所有其他字符自动假定其字面含义。
以下部分描述了可用于制定模式的各种选项:
字符类
围绕字符模式的方括号称为字符类,例如 [abc]
。 字符类总是匹配指定字符列表中的单个字符,这意味着表达式 [abc]
仅匹配 a、b 或 c 字符。
否定字符类也可以定义为匹配除括号内的字符之外的任何字符。 否定字符类是通过在左括号后立即放置一个插入符号 (^
) 来定义的,例如 [^abc]
,它匹配除 a、b 和 C。
您还可以通过在字符类中使用连字符 (-
) 来定义字符范围,例如 [0-9]
。 让我们看一些字符类的例子:
正则表达式 | 它的作用 |
---|---|
[abc] |
匹配任何一个字符 a、b 或 c。 |
[^abc] |
匹配除 a、b 或 c 之外的任何一个字符。 |
[a-z] |
匹配从小写 a 到小写 z 的任意一个字符。 |
[A-Z] |
匹配从大写 a 到大写 z 的任意一个字符。 |
[a-Z] |
匹配从小写 a 到大写 Z 的任意一个字符。 |
[0-9] |
匹配 0 到 9 之间的单个数字。 |
[a-z0-9] |
匹配 a 到 z 或 0 到 9 之间的单个字符。 |
以下示例将向您展示如何使用带有 JavaScript test()
方法的正则表达式来查找字符串中是否存在模式:
var regex = /ca[kf]e/;
var str = "He was eating cake in the cafe.";
// 根据正则表达式测试字符串
if(regex.test(str)) {
alert("Match found!");
} else {
alert("Match not found.");
}
此外,您可以将 全局标志 g
添加到正则表达式以查找字符串中的所有匹配项:
var regex = /ca[kf]e/g;
var str = "He was eating cake in the cafe.";
var matches = str.match(regex);
alert(matches.length); // 输出: 2
提示:正则表达式并非 JavaScript 独有。 Java、Perl、Python、PHP 等语言使用相同的符号来查找文本中的模式。
预定义的字符类
一些字符类(如数字、字母和空格)使用频率很高,以至于它们都有快捷名称。 下表列出了这些预定义的字符类:
快捷方式 | 它的作用 |
---|---|
. |
匹配除换行符 \n 之外的任何单个字符。 |
\d |
匹配任何数字字符。 与 [0-9] 相同 |
\D |
匹配任何非数字字符。 与 [^0-9] 相同 |
\s |
匹配任何空白字符(空格、制表符、换行符或回车符)。 与 [ \t\n\r] 相同 |
\S |
匹配任何非空白字符。 等同于 [^ \t\n\r] |
\w |
匹配任何单词字符(定义为 a 到 z、A 到 Z、0 到 9 和下划线)。 等同于 [a-zA-Z_0-9] |
\W |
匹配任何非单词字符。 等同于 [^a-zA-Z_0-9] |
以下示例将向您展示如何使用带有 JavaScript replace()
方法的正则表达式在字符串中用连字符字符查找和替换空格:
var regex = /\s/g;
var replacement = "-";
var str = "Earth revolves around\nthe\tSun";
// 替换空格、换行符和制表符
document.write(str.replace(regex, replacement) + "<hr>");
// 仅替换空格
document.write(str.replace(/ /g, "-"));
重复量词
在上一节中,我们学习了如何以多种方式匹配单个角色。 但是,如果您想匹配多个字符怎么办? 例如,假设您想找出包含一个或多个字母 p 实例的单词,或者包含至少两个 p 的单词,等等。
这就是量词发挥作用的地方。 使用量词,您可以指定正则表达式中的字符应匹配多少次。 量词可以应用于单个字符,也可以应用于括号中的 字符类和字符组。
下表列出了量化特定模式的各种方法:
正则表达式 | 它的作用 |
---|---|
p+ |
匹配一个或多个出现的字母 p。 |
p* |
匹配零次或多次出现的字母 p。 |
p? |
匹配零次或一次出现的字母 p。 |
p{2} |
恰好匹配两次出现的字母 p。 |
p{2,3} |
匹配至少两次出现的字母 p,但不超过 3 次。 |
p{2,} |
匹配两次或多次出现的字母 p。 |
p{,3} |
最多匹配三个字母 p |
以下示例中的正则表达式将使用 JavaScript split()
方法将字符串拆分为逗号、逗号序列、空格或其组合:
var regex = /[\s,]+/;
var str = "My favourite colors are red, green and blue";
var parts = str.split(regex);
// 循环遍历部件数组并显示子字符串
for(var part of parts){
document.write("<p>" + part + "</p>");
}
定位锚点
在某些情况下,您希望在行、单词或字符串的开头或结尾进行匹配。 为此,您可以使用锚点。 两个常见的锚点是表示字符串开头的插入符号 (^
) 和表示字符串结尾的美元符号 ($
)。
正则表达式 | 它的作用 |
---|---|
^p |
匹配行首的字母 p。 |
p$ |
匹配行尾的字母 p。 |
以下示例中的正则表达式将使用 JavaScript test()
函数仅匹配名称数组中以字母"J"开头的那些名称:
var regex = /^J/;
var names = ["James Bond", "Clark Kent", "John Rambo"];
// 遍历名称数组并显示匹配的名称
for(var name of names) {
if(regex.test(name)) {
document.write("<p>" + name + "</p>")
}
}
模式修饰符(标志)
模式修饰符允许您控制处理模式匹配的方式。 模式修饰符直接放在正则表达式之后,例如,如果要以不区分大小写的方式搜索模式,可以使用 i
修饰符,如下所示:/pattern/i
。
下表列出了一些最常用的模式修饰符。
修饰符 | 它的作用 |
---|---|
g |
执行全局匹配,即查找所有匹配项。 |
i |
使匹配不区分大小写的方式。 |
m |
更改 ^ 和 $ 的行为以匹配换行符边界(即多行字符串中每一行的开始或结束),而不是字符串边界。 |
o |
仅对表达式求值一次。 |
s |
更改 . (点)的行为以匹配所有字符,包括换行符。 |
x |
为了清楚起见,允许您在正则表达式中使用空格和注释。 |
下面的示例将向您展示如何在正则表达式中使用 g
和 i
修饰符来使用 JavaScript match()
方法执行全局且不区分大小写的搜索。
var regex = /color/gi;
var str = "Color red is more visible than color blue in daylight.";
var matches = str.match(regex); // 全局,不区分大小写的匹配
console.log(matches);
// expected output: ["Color", "color"]
同样,以下示例显示如何使用 JavaScript match()
方法使用 ^
锚点和 m
修饰符匹配多行字符串中每一行的开头。
var regex = /^color/gim;
var str = "Color red is more visible than \ncolor blue in daylight.";
var matches = str.match(regex); // 全局,不区分大小写,多行匹配
console.log(matches);
// expected output: ["Color", "color"]
替代
Alternation 允许您指定模式的替代版本。 正则表达式中的交替就像 if-else
条件语句中的 OR
运算符一样工作。
您可以使用竖线 (|
) 指定交替。 例如,正则表达式 /fox|dog|cat/
匹配字符串"fox"、字符串"dog"或字符串"cat"。 这是一个例子:
var regex = /fox|dog|cat/;
var str = "The quick brown fox jumps over the lazy dog.";
var matches = str.match(regex);
console.log(matches);
// expected output: ["fox", index: 16, ...]
注意:从左到右评估备选方案,直到找到匹配项。 如果左选项匹配,则即使右选项匹配,也会完全忽略它。
分组
正则表达式使用括号对子表达式进行分组,就像数学表达式一样。 括号允许将 重复量词 应用于整个子表达式。
例如,在正则表达式 /go+/
中,量词 +
仅应用于最后一个字符 o
,它匹配字符串"go"、"goo"等。 而在正则表达式 /(go)+/
中,量词 +
应用于字符组 g
和 o
,它匹配字符串"go"、"gogo"等。
var regex = /(go)+/i;
var str = "One day Gogo will go to school.";
var matches = str.match(regex); // 不区分大小写匹配
console.log(matches);
// expected output: ["Gogo", "go", index: 8, ...]
注意: 如果字符串与模式匹配,match()
方法会返回一个数组,其中包含整个匹配字符串作为第一个元素,后面是括号中捕获的任何结果,以及整个匹配的索引。 如果未找到匹配项,则返回 null
。
提示: 如果正则表达式包含 g
标志,则 match()
方法只返回一个包含所有匹配子字符串的数组,而不是匹配对象。 不返回捕获的组、整个匹配的索引和其他属性。
单词边界
单词边界字符 (\b
) 可帮助您搜索以模式开头和/或结尾的单词。 例如,正则表达式 /\bcar/
匹配以模式 car 开头的单词,并且会匹配 cart、carrot 或 cartoon,但不会匹配 oscar。
类似地,正则表达式 /car\b/
匹配以模式 car 结尾的单词,并且会匹配 oscar 或 supercar,但不会匹配 cart。 同样,/\bcar\b/
匹配以模式 car 开头和结尾的单词,并且只匹配单词 car。
以下示例将以粗体突出显示以 car 开头的单词:
var regex = /(\bcar\w*)/g;
var str = "Words begining with car: cart, carrot, cartoon. Words ending with car: oscar, supercar.";
var replacement = '<b>$1</b>';
var result = str.replace(regex, replacement);
document.write(result);