正则表达式(Regular Expression)是处理文本信息的强大工具,其应用核心是根据模式(pattern)高效、灵活地匹配文本中的内容,然后,可以对匹配内容进行删除、替换、修改等操作。本文将介绍JavaScript中的正则表达式应用。
JavaScript正则表达式模式的定义格式为:/<模式>/<修饰符>,定义的模式实际是RegExp类型的对象。其中 ,<模式>的定义稍后会详细介绍,先来看<修饰符>使用,修饰符可以看作正则表达式工作的参数;常用的修饰符包括:
定义模式中会使用一些有着特殊含义的元字符,就像编程语言中的关键字一样。下面是正则表达式模式中的元字符。
在模式中需要匹配这些字符时,需要使用\字符转义,如\\表示\字符、\.表示圆点等。此外,对于一些特殊的字符,也需要使用\字符转义,与字符串中的转义字符应用类似,如:
创建RegExp对象有两种方法,一是直接使用/符号和修饰符定义的模式,其返回的就是RegExp对象。另一种方法是使用RegExp构造函数,其中,参数一使用字符串定义模式,其中,对于模式中转义字符的\字符需要先进行字符串转义,如"\\d"表示模式中的\d(匹配一个数字);参数二使用字符串指定模式的修饰符,可以是g、i、m、s、u、y、v的组合,如"gi"。
RegExp对象的属性包括:
RegExp对象的方法包括:
下面的代码会匹配字符串abc,并且不区分大小写。
<script> let p = /abc/gi let s = "abc,def,abc,ghi"; alert(p.test(s)); // true alert(p.source); // abc alert(p.flags); // gi alert(p.global); // true alert(p.ignoreCase); // true alert(p.unicode); // false </script>
代码中,首先定义了模式/abc/,即匹配abc字符串,使用g和i修饰符表示搜索全部字符串并忽略字母大不写。变量s定义了一些字符串内容。p.test(s)方法会在s中匹配abc,执行结果会显示true。接下来的几个alert()函数调用显示了p对象的几个只读属性值。
下面的代码演示了exec()方法的应用。
<script> let p = /abc/gi let s = "abc,def,ABC,ghi"; while ((m = p.exec(s)) !== null) { alert(m); } </script>
本例会显示字符串中的"abc"和"ABC"。
String对象处理字符串时,有一些方法也可以使用正则表达式,下面分别介绍。
match(p)方法,返回所有匹配内容组成的数组,与RegExp对象的exec()方法功能相似;下面的代码演示了相关应用。
<script> let p = /abc/gi let s = "abc,def,ABC,ghi"; let arr = s.match(p); for (let m of arr) { alert(m); } </script>
执行代码会依次显示abc和ABC。
matchAll(p)方法,返回所有匹配内容的迭代器,下面的代码演示了相关应用。
<script> let p = /abc/gi let s = "abc,def,ABC,ghi"; for (let m of s.matchAll(p)) { alert(m); } </script>
执行代码同样会显示abc和ABC。
search(p),返回第一个匹配内容的索引位置,没有匹配内容时返回-1。下面的代码演示了相关应用。
<script> let p = /abc/gi let s = "abc,def,ABC,ghi"; alert(s.search(p)); // 0 alert(s.search(/xyz/gi)); // -1 </script>
split(p)方法,按照模式分割字符串,返回分割后的数组。可以使用第二个参数指定返回数组的元素数量。下面的代码演示了相关应用。
<script> let p = /,/g; let s = "abc,def,ghi,jkl"; let arr1 = s.split(p); let arr2 = s.split(p, 3); alert(arr1.length); // 4 alert(arr2.length); // 3 </script>
代码中,定义使用逗号(,)分割字符串。arr1数组保存了全部分分割内容,其元素有4个(使用length属性显示),分别是abc、def、ghi和jkl。arr2数组则保留了前3个分割元素,分别是abc、def和jkl。
replace(p,s)方法,将模式匹配的内容替换为参数s指定的内容。下面的代码演示了相关应用。
<script> let p = /abc/gi; let s = "abc,def,ABC,jkl"; alert(s.replace(p, "***")); // ***,def,***,jkl </script>
本例会将s字符串中的abc和ABC替换为***,显示结果为***,def,***,jkl。
前面已经介绍了如何使用RegExp和String对象操作正则表达式和字符串,下面介绍更多关于模式定义的内容,包括如何定义匹配内容、匹配次数和匹配位置等。
在模式定义中定义匹配的内容时,主要包括以下一些方法:
除了匹配内容,还可以指定匹配的次数,如:
常用的位置匹配方法如下:
下面的代码演示了如何匹配11位手机号码。
<script> let p = /^1\d{10}$/g let s = "12345678910"; alert(p.test(s)); // true </script>
本例,定义的模式以数字1开始(^1),以10位数字结束(\d{10}$),可以修改字符串s的内容观察执行结果。
下面的代码演示了贪婪模式和非贪婪模式的区别。
<script> let p1 = /a+/g; let p2 = /a+?/g; let s = "aaa"; alert(p1.exec(s)); // aaa alert(p2.exec(s)); // a </script>
贪婪模式下会尽可能多的匹配内容,如p1模式中可以匹配1个或多个字母a,默认使用贪婪模式,会匹配全部的三个字母a。p2模式使用了非贪婪模式,当它匹配到第一个a时即停止搜索。
下面的代码演示了|运算符和单词边界的匹配。
<script> let p = /\b(J|T)\w+\b/gi; let s = "Smith John Jerry Frank Tom Timmy"; let arr = s.match(p); for (let m of arr) { alert(m); } </script>
本例,模式的含义是以J或T开始的单词,然后最少有一个单词字符,开始和结束的\b表示单词的边界。执行代码会依次显示John、Jerry、Tom和Timmy。此外,(J|T)修改为[JT]也可以有相同的效果。
本文介绍了正则表达式的基础应用,后续文章还会有更多正则表达式和字符串处理的讨论。