上一章JavaScript教程请查看:JS错误处理
在本教程中,我们将了解正则表达式如何工作,以及如何使用它们在JavaScript中高效地执行模式匹配。
什么是正则表达式?正则表达式通常称为“regex”或“RegExp”,是一种特殊格式的文本字符串,用于在文本中查找模式。正则表达式是目前最强大的有效文本处理和操作工具之一。例如,它可以用来验证用户输入的数据格式,如姓名、电子邮件、电话号码等是否正确,查找或替换文本内容中的匹配字符串,等等。
JavaScript支持Perl风格的正则表达式。为什么使用Perl样式的正则表达式?因为Perl(实用提取和报告语言)是第一个为正则表达式提供集成支持的主流编程语言,它以对正则表达式的强大支持和非凡的文本处理和操作能力而闻名。
在深入研究正则表达式之前,让我们先简要概述一下用于执行模式匹配的常用JavaScript内置方法。
函数 | 解释 |
exec() | 在字符串中搜索匹配项。如果不匹配,它将返回一个信息数组或null。 |
test() | 测试字符串是否与模式匹配。它返回true或false。 |
search() | 在字符串中搜索匹配项。它返回第一个匹配项的索引,如果没有找到则返回-1。 |
replace() | 搜索字符串中的匹配项,并用替换字符串替换匹配的子字符串。 |
match() | 在字符串中搜索匹配项。如果不匹配,它将返回一个信息数组或null。 |
split() | 使用正则表达式将字符串分割成子字符串数组。 |
定义正则表达式在JavaScript中,正则表达式由RegExp对象表示,它是一个原生JavaScript对象,如字符串、数组等。创建新RegExp对象有两种方法——一种是使用文字语法,另一种是使用RegExp()构造函数。
文字语法使用斜杠(/pattern/)来包装正则表达式模式,而构造函数语法使用引号(“pattern”)。下面的示例演示了创建匹配任何以“mr”开头的字符串的正则表达式的两种方法。
// 字面量语法
var regex = /^Mr\./;
// 构造函数的语法
var regex = new RegExp("^Mr\\.");
如你所见,正则表达式文字语法更短,更容易阅读,因此,最好使用文字语法,在本教程中,我们还将使用它。
注意:在使用构造函数语法时,必须双转义特殊字符,这意味着要匹配“.”,你需要写“\\.”而不是“\.”,如果只有一个反斜杠,它将被JavaScript的字符串解析器解释为转义字符并删除。
正则表达式匹配模式 正则表达式模式包括使用字母、数字、标点符号等,加上一组特殊的正则表达式字符(不要与HTML特殊字符混淆)。
在正则表达式中被赋予特殊含义的字符有:
.* ?+[](){} ^ $ | \.当你想按字面意思使用这些字符时,你需要反斜杠。例如,如果你想匹配“.”,你必须编写\.,所有其他字符自动假定它们的字面意义。
以下各节描述了可用于制定模式的各种选择:
字符类围绕字符模式的方括号称为字符类,如[abc],字符类总是匹配指定字符列表中的单个字符,这意味着表达式[abc]只匹配A、b或c字符。
反字符类还可以定义为匹配除括号内包含的字符之外的任何字符。反字符类的定义是将插入符号(^)放在首括号之后,就像[^abc],它匹配除A、b和c之外的任何字符。
还可以在字符类中使用连字符(-)来定义字符范围,如[0-9]。让我们来看一些字符类的例子:
RegExp | 解释 |
[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之间的单个字符。 |
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 | 匹配任何空白字符(空格、制表符、换行符或回车符)。 |
\S | 与[\t\n\r]相同 |
\w | 匹配任何非空白字符。 |
\W | 与[^ \t\n\r]相同 |
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的单词。
这就是量词发挥作用的地方。使用量词,你可以指定正则表达式中的字符应该匹配多少次。量词可以应用于单个字符、字符类和圆括号中包含的字符组。
下表列出了量化特定模式的各种方法:
RegExp | 解释 |
p+ | 匹配字母p的一个或多个匹配项。 |
p* | 匹配字母p的零次或多次出现。 |
p? | 匹配字母p的零次或一次出现。 |
p{2} | 恰好匹配两个字母p。 |
p{2,3} | 至少匹配两个字母p,但不超过三个。 |
p{2,} | 匹配两个或多个字母p。 |
p{,3} | 最多匹配三个字母p |
var regex = /[\s,]+/;
var str = "My favourite colors are red, green and blue";
var parts = str.split(regex);
// 循环通过part显示子字符串
for(var part of parts){
document.write("<
p>" + part + "<
/p>");
}
位置定位在某些情况下,需要在行、词或字符串的开头或结尾进行匹配。为此,你可以使用锚。两个常见的锚点是表示字符串开始的插入符号(^)和表示字符串结束的美元符号($)。
RegExp | 解释 |
^p | 匹配行首的字母p。匹配一行末尾的字母p。 |
p$ | 匹配行首的字母p。匹配一行末尾的字母p。 |
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 | 允许你在正则表达式中使用空白和注释以保持清晰。 |
var regex = /color/gi;
var str = "Color red is more visible than color blue in daylight.";
var matches = str.match(regex);
// 全局不区分大小写的匹配
console.log(matches);
// : ["Color", "color"]
类似地,下面的示例展示了如何使用^锚和m修饰符以及JavaScript match()方法在多行字符串的每一行的开头进行匹配。
var regex = /^color/gim;
var str = "Color red is more visible than \ncolor blue in daylight.";
var matches = str.match(regex);
// 全局,不区分大小写,多行匹配
console.log(matches);
// : ["Color", "color"]
交替交替允许你指定模式的替代版本,正则表达式中的替换就像if-else条件语句中的OR操作符一样工作。
可以使用竖线(|)指定替换。例如,regexp /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);
// : ["fox", index: 16, ...]
注意:从左到右计算备选项,直到找到匹配项为止,如果左可选项匹配,则即使有匹配项,也会完全忽略右可选项。
分组正则表达式使用括号将子表达式分组,就像数学表达式一样,圆括号允许将重复量词应用于整个子表达式。
例如,在regexp /go+/量词+只应用于最后一个字符o,它匹配字符串“go”、“goo”等。然而,在regexp /(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);
// : ["Gogo", "go", index: 8, ...]
注意:如果字符串与模式匹配,match()方法将返回一个数组,其中包含作为第一个元素的整个匹配字符串,然后是括号中捕获的任何结果,以及整个匹配的索引。如果没有找到匹配项,则返回null。
提示:如果正则表达式包含g标志,match()方法只返回一个包含所有匹配子字符串的数组,而不是match对象。不返回捕获的组、整个匹配的索引和其他属性。
单词边界单词边界字符(\b)帮助你搜索以模式开头和/或结尾的单词。例如,regexp /\bcar/匹配以模式car开头的单词,并将匹配cart、carrot或cartoon,但不匹配oscar。
类似地,regexp /car\b/匹配以模式car结尾的单词,并将匹配oscar或supercar,但不匹配cart。同样,/\bcar\b/将开头和结尾的单词与模式car匹配,并且只匹配单词car。
【JS正则表达式 – JavaScript高级教程】下面的示例将突出显示以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);
推荐阅读
- JS表单验证 – JavaScript高级教程
- JS错误处理 – JavaScript高级教程
- JS JSON转换 – JavaScript高级教程
- JS严格模式 – JavaScript高级教程
- 如何使用Java中的List接口(代码实例)
- JS闭包和闭包函数 – JavaScript高级教程
- JS函数提升和变量提升 – JavaScript高级教程
- JS借用调用方法 – JavaScript高级教程
- JS事件传播机制 – JavaScript高级教程