JS正则表达式 – JavaScript高级教程

上一章JavaScript教程请查看:JS错误处理
在本教程中,我们将了解正则表达式如何工作,以及如何使用它们在JavaScript中高效地执行模式匹配。
什么是正则表达式?正则表达式通常称为“regex”或“RegExp”,是一种特殊格式的文本字符串,用于在文本中查找模式。正则表达式是目前最强大的有效文本处理和操作工具之一。例如,它可以用来验证用户输入的数据格式,如姓名、电子邮件、电话号码等是否正确,查找或替换文本内容中的匹配字符串,等等。
JavaScript支持Perl风格的正则表达式。为什么使用Perl样式的正则表达式?因为Perl(实用提取和报告语言)是第一个为正则表达式提供集成支持的主流编程语言,它以对正则表达式的强大支持和非凡的文本处理和操作能力而闻名。
在深入研究正则表达式之前,让我们先简要概述一下用于执行模式匹配的常用JavaScript内置方法。

函数 解释
exec() 在字符串中搜索匹配项。如果不匹配,它将返回一个信息数组或null。
test() 测试字符串是否与模式匹配。它返回true或false。
search() 在字符串中搜索匹配项。它返回第一个匹配项的索引,如果没有找到则返回-1。
replace() 搜索字符串中的匹配项,并用替换字符串替换匹配的子字符串。
match() 在字符串中搜索匹配项。如果不匹配,它将返回一个信息数组或null。
split() 使用正则表达式将字符串分割成子字符串数组。
注意:exec()和test()方法是将字符串作为参数的RegExp方法,而search()、replace()、match()和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之间的单个字符。
下面的示例将向你展示如何使用带有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 匹配任何空白字符(空格、制表符、换行符或回车符)。
\S 与[\t\n\r]相同
\w 匹配任何非空白字符。
\W 与[^ \t\n\r]相同
下面的示例将向你展示如何使用带有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的单词。
这就是量词发挥作用的地方。使用量词,你可以指定正则表达式中的字符应该匹配多少次。量词可以应用于单个字符、字符类和圆括号中包含的字符组。
下表列出了量化特定模式的各种方法:
RegExp 解释
p+ 匹配字母p的一个或多个匹配项。
p* 匹配字母p的零次或多次出现。
p? 匹配字母p的零次或一次出现。
p{2} 恰好匹配两个字母p。
p{2,3} 至少匹配两个字母p,但不超过三个。
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); // 循环通过part显示子字符串 for(var part of parts){ document.write("< p>" + part + "< /p>"); }

位置定位在某些情况下,需要在行、词或字符串的开头或结尾进行匹配。为此,你可以使用锚。两个常见的锚点是表示字符串开始的插入符号(^)和表示字符串结束的美元符号($)。
RegExp 解释
^p 匹配行首的字母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); // : ["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);

    推荐阅读