《JavaScript权威指南》阅读笔记(8) 正则表达式的模式匹配

第 10 章 正则表达式的模式匹配

正则表达式是一个描述字符串模式的对象。

JavaScript的RegExp类表示正则表达式,String和RegExp都定义了方法,后者使用正则表达式进行强大的模式匹配和文本与替换功能。

正则表达式的定义

JavaScript中正则表达式用RegExp对象表示,可以使用RegExp()构造函数来创建RegExp对象,不过RegExp对象更多的是通过一种特殊的直接量语法来创建。就像通过引号包裹字符的方式来定义字符串直接量一样,正则表达式直接量定义为包含在一堆斜杆(/)之间的字符。例如:

var pattern = /s$/; 
//这段代码创建一个新的RegExp对象,并将它赋值给变量pattern。这个特殊的RegExp对象用来匹配所有以字母"s"结尾的字符串。
//用构造函数RegExp()也可以定义个与之等价的正则表达式,代码如下:
var pattern = new RegExp("s$");

RegExp直接量和对象的创建

就像字符串和数字一样,程序中每个取值相同的原始类型直接量均表示相同的值,这是显而易见。程序运行每次遇到对象直接量(初始化表达式)诸如{}和[]的时候都会创建新对象。比如,如果在循环中写var a = [],则每次遍历都会创建一个新的空数组。

正则表达式直接量则与此不同,ECMAScript5规定 同一段代码所表示的正则表达式直接量的每次运算都返回新对象。

直接量字符

字符 匹配

字母和数字字符 自身

\o NUL字符

\t 制表符

\n 换行符

\v 垂直制表符

\f 换页符

\r 回车符

\xnn 由十六进制数nn指定的拉丁字符

\uxxxx 由十六进制数xxxx指定的Unicode字符

\cX 控制字符^X

正则表达式的字符类:

字符 匹配

[...] 方括号内的任意字符

[^...] 不在方括号内的任意字符

. 除换行符和其他Unicode行终止符之外的任意字符

\w 任何ASCII字符组成的单词,等价于[a-zA-Z0-9]

\W 任何不是ASCII字符组成的单词,等价于[^a-zA-Z0-9]

\s 任何Unicode空白符

\S 任何非Unicode空白符的字符,注意\w\S不同

\d 任何ASCII数字,等价于[0-9]

\D 除了ASCII数字之外的任何字符,等价于[^0-9]

[\b] 退格直接量

正则表达式的重复字符语法:

字符 含义

{n, m} 匹配前一项至少n次,但不能超过m次

{n, } 匹配前一项n次或更多次

{n} 匹配前一项n次

? 匹配前一项0次或者1次,也就是说前一项是可选的

+ 匹配前一项1次或者多次,等价于{1, }

* 匹配前一项0次或多次,等价于{0, }

非贪婪的重复

只须在待匹配的字符后跟随一个问号即可:“??”、“+?”、“*?”或“{1,5}?”。

选择、分组和引用

字符 含义

| 选择,匹配的是该符号左边的子表达式或者右边的子表达式。若左边的选择项匹配,就忽略右边的匹配项,即使它产生更好的匹配。

(...) 组合,将几个项组合为一个单元,这个单元可通过 “*”、“+”、“”和“|”等符号加以修饰,而且可以记住和这个组合相匹配的字符串以供此后的引用使用。

(?:...) 只组合,把项组合到一个单元,但不记忆与该组相匹配的字符。

\n 和第n个分组第一次匹配到字符相匹配,组是圆括号中的子表达式(也可能是嵌套的)。组索引是从左到右的左括号,“(?:”形式的分组不编码。

指定匹配位置

字符 含义

^ 匹配字符串的开头,在多行检索中,匹配一行的开头

$ 匹配字符串的结尾,在多行检索中,匹配一行的结尾

\b 匹配一个单词的边界,简言之,就是位于字符\w\W之间的位置,或者位于字符\w和字符串的开头或者结尾之间的位置。([\b]匹配的是退格符)

\B 匹配非单词边界的位置

(?=p) 零宽正向先行断言,要求接下来的字符都与p匹配,但不能包括匹配p的那些字符

(?!p) 零宽负向先行断言,要求接下来的字符不与p匹配

修饰符

字符 含义

i 执行不区分大小写的匹配

g 执行一个全局匹配,即找到所有的匹配,而不是在找到第一个之后就停止

m 多行匹配模式,^匹配一行的开头和字符串的开头,$匹配行的结束和字符串的结束

用于模式匹配的String方法

String支持4种正则表达式的方法。

search() :

它的参数是一个正则表达式,返回一个与子匹配的子串的起始位置,如果找不到匹配的子串,它将返回-1 。

"JavaScript".search(/script/i); //返回值为4

如果search()的参数不是正则表达式,则首先会通过RegExp构造函数将它转换成正则表达式,search()方法不支持全局检索,因为它忽略正则表达式参数中的修饰符g。

replace() :

它的第一个参数是一个正则表达式,第二个参数是要进行替换的字符串。

该方法会调用它的字符串进行检索,使用指定的模式来匹配。

如果正则表达式中设置了修饰符g,那么源字符串中所有与模式匹配的子串都将替换成第二个参数指定的字符串;如果不带修饰符g则只替换所匹配的第一个子串。

如果replace()的第一个参数是字符串而不是正则表达式,则replace()将直接搜索这个字符串,而不是像search()一样首先通过RegExp()将它转换为正则表达式。

//将文本中所有javascript统一替换为"JavaScript":
text.replace(/javacsript/gi,"JavaScript");

如果在替换字符串中出现了$数字,那么replace()将用与指定子表达式相匹配的文本来替换这两个字符。

//将一个字符串中的英文引号替换为中文半角引号:
//一段引用文本起始于引号,结束与引号
//中间的内容区域不能包含引号
var quote = /"([^"]*)"/g;
//用中文半角引号替换英文引号,同时要保持引号之间的内容没有被修改
text.replace(quote, '“$1”');

replace()方法的第二个参数可以是函数,该函数能够动态地计算替换字符串。

match() :

它的唯一参数就是一个正则表达式,返回的是一个由匹配结果组成的数组。

如果该正则表达式设置了修饰符g,则该方法返回的数组包含字符串中所有匹配结果。

"1 plus 2 equals 3".match(/\d+/g/) //返回["1", "2", "3"]

如果这个正则表达式没有设置修饰符g,match()就不会进行全局检索,它只检索第一个匹配。但即使match()执行的不是全局检索,它也返回一个数组。在这种情况下,数组的第一个元素就是匹配的字符串,余下的元素则是正则表达式中用圆括号括起来的子表达式。因此,如果match()返回一个数组a,那么a[0]存放的是完整的匹配,a[1]存放的则是与第一个用圆括号括起来的表达式相匹配的子串,以此类推。为了和方法replace()保持一致,a[n]存放的是$n的内容。

var url = /(\w+):\/\/([\w.]+)\/(\S*)/;
var text = "Visit my blog at http://www.example.com/~david";
var result = text.match(url);
if (result != null) {
var fullurl = result[0]; //包含"http://www.example.com/~david"
var protocol = result[1]; //包含"http"
var host = result[2]; //包含"www.example.com"
var path = result[3]; //包含"~david"
}

split() :

这个方法用以调用它的字符串拆分为一个子串组成的数组,使用的分隔符是split()的参数。

split()方法的参数也可以是一个正则表达式。

"123,456,789".split(","); //返回["123", "456", "789"];

//指定分隔符,允许两边可以留有任意多的空白符:
"1, 2, 3, 4, 5".split(/\s*,\*/); //返回["1","2","3","4","5"]

RegExp对象

RegExp()构造函数带有两个字符串参数,其中第二个参数是可选的,RegExp()用以创建新的RegExp对象。

第一个参数包容正则表达式的主体部分,也就是正则表达式直接量中两条斜线之间的文本。第二个参数是可选的,如果提供第二个参数,它就指定正则表达式的修饰符。不过只能传入修饰符g, i, m 或者它们的组合。

//全局匹配字符串中的5个数字,注意这里使用了"\\",而不是"\"
var zipcode = new RegExp("\\d{5}", "g");

exec() :

参数是一个字符串。该方法对一个指定的字符串执行一个正则表达式,简言之,就是在一个字符串中执行匹配检索。如果它没有任何匹配,就返回null,但如果它找到了一个匹配,它就返回一个数组。这个数组的第一个元素包含的与正则表达式相匹配的字符串,余下的元素是与圆括号内的子表达式相匹配的子串。属性index包含了发生匹配的字符串位置,属性input引用的是正在检索的字符串。

不管正则表达式是否具有全局修饰符g,exec()都会返回一样的数组。

当调用exec()的正则表达式对象具有修饰符g时,它将当前正则表达式对象的lastIndex属性设置为紧挨着匹配字符串位置。当同一个正则表达式第二次调用exec()时,它将从lastIndex属性所指示的字符处开始检索。如果exec()没有发现任何匹配结果,它会将lastIndex重置为0。

test() :

它的参数是一个字符串,用test()对某个字符串进行检测,如果包含正则表达式的一个匹配结果,则返回true:

var pattern = /java/i;
pattern.test("JavaScript"); //返回true

调用test()和调用exec()等价,当exec()的返回结果不是null时,test()返回true。由于这种等价性,当一个全局正则表达式调用方法test()时,它的行为和exec()相同。(在lastIndex上也相同)

与exec()和test()不同,String方法search()、replace()和match()并不会用到lastIndex属性。实际上,String方法只是简单地将lastIndex属性重置为0。如果让一个带有修饰符g的正则表达式对多个字符串执行exec()或test(),要么在每个字符串中找出所有的匹配以便将lastIndex自动重置为零,要么显示将lastIndex手动设置为0(当最后一次检索失败时需要手动设置lastIndex)。如果忘了手动设置lastIndex的值,那么下一次对新字符串进行检索时,执行检索的起始位置可能就不是字符串的开始位置,而可能是任意位置(由lastIndex决定)。当然,如果RegExp不带有修饰符g,则不必担心会发生这种情况。

发布了60 篇原创文章 · 获赞 121 · 访问量 7554

猜你喜欢

转载自blog.csdn.net/weixin_46124214/article/details/104464748
今日推荐