下面小编就为大家带来一篇 javascript 类型系统_正则表达式 RegExp 类型详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
前面的话
前面已经介绍过 javascript 中正则表达式的基础语法。javascript 的 RegExp 类表示正则表达式,String 和 RegExp 都定义了方法,使用正则表达式可以进行强大的模式匹配和文本检索与替换。本文将介绍正则表达式的 RegExp 对象,以及正则表达式涉及
到的属性和方法
对象
javascript 中的正则表达式用 RegExp 对象表示,有两种写法:一种是字面量写法;另一种是构造函数写法
Perl 写法
正则表达式字面量写法,又叫 Perl 写法,因为 javascript 的正则表达式特性借鉴自 Perl
正则表达式字面量定义为包含在一对斜杠 (/) 之间的字符,并且可以设置 3 个标志
var expression = /pattern/flags;
正则表达式的匹配模式支持下列 3 个标志:
g: 表示全局 (global) 模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即停止
i: 表示不区分大小写 (case-insensitive) 模式,即在确定匹配项时忽略模式与字符串的大小写
m: 表示多行 (multiline) 模式,即在到达一行文本末尾时还会继续查找下一行中是否存在与模式匹配的项
- //匹配字符串所有'at'的实例
- var p = /at/g;
- //test()方法返回一个布尔值表示是否可以找到匹配项
- console.log(p.test('ata')); //true
- console.log(p.test('aba')); //false
RegExp 构造函数
和普通的内置对象一样,RegExp 正则表达式对象也支持 new+RegExp() 构造函数的形式
RegExp 构造函数接收两个参数:要匹配的字符串模式 (pattern) 和可选的标志字符串(flags),标志字符串和字面量的三个标志含义相同:'g'、'i'、'm'
RegExp 构造函数的两个参数都是字符串。且使用字面量形式定义的任何表达式都可使用构造函数
- //匹配字符串所有'at'的实例
- var p1 = /at/g;
- //同上
- var p2 = new RegExp('at','g');
[注意]ECMAScript3 规范规定,一个正则表达式直接量会在执行到它时转换为一个 RegExp 对象,同一段代码所表示正则表达式直接量的每次运算都返回同一个对象。ECMAScript5 规范则做了相反的规定,同一段代码所表示的正则表达式直接量的每次
运算都返回新对象。IE6-8 一直是按照 ECMAScript5 规范的方式实现的,所以并没有兼容性问题
由于正则表达式字面量并不支持变量,所以如果正则表达式中出现变量只能使用 RegExp 构造函数以字符串拼接的形式,将变量拼接到 RegExp 构造函数的参数中
【tips】通过类名 classname 获取元素
- function getByClass(obj,classname){
- var elements = obj.getElementsByTagName('*');
- var result = [];
- var pattern = new RegExp( '(^|\\s)'+ classname + '(\\s|$)');
- for(var i = 0; i < elements.length; i++){
- if(pattern.test(elements[i].className)){
- result.push(elements[i]);
- }
- }
- return result;
- }
实例属性
每个 RegExp 实例对象都包含如下 5 个属性
- global: 布尔值,表示是否设置了g标志
- ignoreCase: 布尔值,表示是否设置了i标志
- lastIndex: 整数,表示开始搜索下一个匹配项的字符位置,从0算起
- multiline: 布尔值,表示是否设置了标志m
- source: 正则表达式的字符串表示,按照字面量形式而非传入构造函数中的字符串模式返回
- var pattern = new RegExp('\\[bc\\]at', 'i');
- console.log(pattern.global); //false
- console.log(pattern.ignoreCase); //true
- console.log(pattern.multiline); //false
- console.log(pattern.lastIndex); //0
- console.log(pattern.source); //'\[bc\]at'
如果使用 RegExp 的 exec() 或 test() 函数,并且设定了全局模式'g',正则表达式的匹配就会从 lastIndex 的位置开始,并且在每欠匹配成功之后重新设定 lastIndex。这样,就可以在字符串中重复迭代,依次寻找各个匹配结果。但是,如果需要对不同字符串调用同一个 RegExp 的 exec() 或 test() 方法,这个变量也也可能会带来意料之外的匹配结果,所以在更换字符串时,要显式地将 RegExp 的 lastIndex 置为 0
- //exec()方法以数组形式返回匹配项
- var p = /\w/g;
- var s = 'ab';
- console.log(p.lastIndex); //0
- console.log(p.exec(s)); //['a']
- console.log(p.lastIndex); //1
- console.log(p.exec(s)); //['b']
- console.log(p.lastIndex); //2
- console.log(p.exec(s)); //null
- console.log(p.lastIndex); //0
- var p = /\w/g;
- var s1 = 'ab';
- var s2 = 'ba';
- console.log(p.lastIndex); //0
- console.log(p.exec(s1)); //['a']
- console.log(p.lastIndex); //1
- console.log(p.exec(s2)); //['a']
- console.log(p.lastIndex); //2
构造函数属性
RegExp 构造函数属性被看成静态属性,这些属性基于所执行的最近一次正则表达式操作而变化
有两种方式访问它们,即长属性名和短属性名。短属性名大都不是有效的 ECMAScript 标识符,所以必须通过方括号语法来访问它们
- 长属性名 短属性名 说明
- input $_ 最近一次要匹配的字符串
- lastMatch $& 最近一次的匹配项
- lastParen $+ 最近一次匹配的捕获组
- leftContext $` input字符串中lastMatch之前的文本
- multiline $* 布尔值,表示是否所有表达式都使用多行模式
- rightContext $' Input字符串中lastMarch之后的文本
使用这些属性,可以从 exec() 方法或 test() 方法执行的操作中提取出更具体的信息
- //test()用于测试一个字符串是否匹配某个正则表达式,并返回一个布尔值
- var text = 'this has been a short summer';
- var pattern = /(.)hort/g;
- if(pattern.test(text)){
- console.log(RegExp.input);//'this has been a short summer'
- console.log(RegExp.leftContext);//'this has been a '
- console.log(RegExp.rightContext);//' summer'
- console.log(RegExp.lastMatch);//'short'
- console.log(RegExp.lastParen);//'s'
- console.log(RegExp.multiline);//false
- console.log(RegExp['$_']);//'this has been a short summer'
- console.log(RegExp['$`']);//'this has been a '
- console.log(RegExp["$'"]);//' summer'
- console.log(RegExp['$&']);//'short'
- console.log(RegExp['$+']);//'s'
- console.log(RegExp['$*']);//false
- }
javascript 有 9 个用于存储捕获组的构造函数属性,在调用 exec() 或 test() 方法时,这些属性会被自动填充
[注意] 理论上,应该保存整个表达式匹配文本的 RegExp.$0 并不存在,值为 undefined
- //RegExp.$1\RegExp.$2\RegExp.$3……到RegExp.$9分别用于存储第一、第二……第九个匹配的捕获组
- var text = 'this has been a short summer';
- var pattern = /(..)or(.)/g;
- if(pattern.test(text)){
- console.log(RegExp.$1);//sh
- console.log(RegExp.$2);//t
- }
实例方法
RegExp 对象的实例方法共 5 个,分为两类。包括 toString()、toLocalString()、valueOf() 这 3 种对象通用方法和 test()、exec() 正则匹配方法
对象通用方法
RegExp 对象继承了 Object 对象的通用方法 toString()、toLocaleString()、valueOf() 这三个方法
【toString()】
toString() 方法返回正则表达式的字面量
【toLocaleString()】
toLocaleString() 方法返回正则表达式的字面量
【valueOf()】
valueOf() 方法返回返回正则表达式对象本身
[注意] 不论正则表达式的创建方式是哪种,这三个方法都只返回其字面量形式
- var pattern = new RegExp('[bc]at', 'gi');
- console.log(pattern.toString()); // '/[bc]at/gi'
- console.log(pattern.toLocaleString()); // '/[bc]at/gi'
- console.log(pattern.valueOf()); // /[bc]at/gi
- var pattern = /[bc]at/gi;
- console.log(pattern.toString()); // '/[bc]at/gi'
- console.log(pattern.toLocaleString()); // '[bc]at/gi'
- console.log(pattern.valueOf()); // /[bc]at/gi
正则匹配方法
正则表达式 RegExp 对象的正则匹配方法只有两个:分别是 exec() 和 test()
【exec()】
exec() 方法专门为捕获组而设计,接受一个参数,即要应用模式的字符串。然后返回包含匹配项信息的数组,在没有匹配项的情况下返回 null
在匹配项数组中,第一项是与整个模式匹配的字符串,其他项是与模式中的捕获组匹配的字符串,如果模式中没有捕获组,则该数组只包含一项
返回的数组包含两个额外的属性:index 和 input。index 表示匹配项在字符串的位置,input 表示应用正则表达式的字符串
- var text = 'mom and dad and baby and others';
- var pattern = /mom( and dad( and baby)?)?/gi;
- var matches = pattern.exec(text);
- console.log(pattern, matches);
- //pattern.lastIndex:20
- //matches[0]:'mom and dad and baby'
- //matches[1]:' and dad and baby'
- //matches[2]:' and baby'
- //matches.index:0
- //matches.input:'mom and dad and baby and others'
对于 exec()方法而言,即使在模式中设置了全局标志 (g),它每次也只会返回一个匹配项。在不设置全局标志的情况下,在同一个字符串上多次调用 exec(),将始终返回第一个匹配项的信息;而在设置全局标志的情况下,每次调用 exec() 都会在字符串中继续查找新匹配项
- var text = 'cat,bat,sat,fat';
- var pattern1 = /.at/;
- var matches = pattern1.exec(text);
- console.log(pattern1, matches);
- //pattern1.lastIndex:0
- //matches[0]:'cat'
- //matches.index:0
- //matches.input:'cat,bat,sat,fat'
- var text = 'cat,bat,sat,fat';
- matches = pattern1.exec(text);
- console.log(pattern1, matches);
- //pattern1.lastIndex:0
- //matches[0]:'cat'
- //matches.index:0
- //matches.input:'cat,bat,sat,fat'
- var text = 'cat,bat,sat,fat';
- var pattern2 = /.at/g;
- var matches = pattern2.exec(text);
- console.log(pattern2, matches);
- //pattern2.lastIndex:3
- //matches[0]:'cat'
- //matches.index:0
- //matches.input:'cat,bat,sat,fat'
- var text = 'cat,bat,sat,fat';
- matches = pattern2.exec(text);
- console.log(pattern2, matches);
- //pattern2.lastIndex:7
- //matches[0]:'bat'
- //matches.index:4
- //matches.input:'cat,bat,sat,fat'
【tips】用 exec() 方法找出匹配的所有位置和所有值
- var string = 'j1h342jg24g234j 3g24j1';
- var pattern = /\d/g;
- var valueArray = [];//值
- var indexArray = [];//位置
- var temp;
- while((temp=pattern.exec(string)) != null){
- valueArray.push(temp[0]);
- indexArray.push(temp.index);
- }
- //["1", "3", "4", "2", "2", "4", "2", "3", "4", "3", "2", "4", "1"] [1, 3, 4, 5, 8, 9, 11, 12, 13, 16, 18, 19, 21]
- console.log(valueArray,indexArray);
【test()】
test() 方法用来测试正则表达式能否在字符串中找到匹配文本,接收一个字符串参数,匹配时返回 true,否则返回 false
- var text = '000-00-000';
- var pattern = /\d{3}-\d{2}-\d{4}/;
- if(pattern.test(text)){
- console.log('The pattern was matched');
- }
同样地,在调用 test() 方法时,会造成 RegExp 对象的 lastIndex 属性的变化。如果指定了全局模式,每次执行 test() 方法时,都会从字符串中的 lastIndex 偏移值开始尝试匹配,所以用同一个 RegExp 多次验证不同字符串,必须在每次调用之后,将 lastIndex 值置为 0
- var pattern = /^\d{4}-\d{2}-\d{2}$/g;
- console.log(pattern.test('2016-06-23')); //true
- console.log(pattern.test('2016-06-23')); //false
- //正确的做法应该是在验证不同字符串前,先将lastIndex重置为0
- var pattern = /^\d{4}-\d{2}-\d{2}$/g;
- console.log(pattern.test('2016-06-23')); //true
- pattern.lastIndex = 0;
- console.log(pattern.test('2016-06-23')); //true
前面介绍过,javascript 有 9 个用于存储捕获组的构造函数属性,在调用 exec() 或 test() 方法时,这些属性会被自动填充
[注意] 理论上,应该保存整个表达式匹配文本的 RegExp.$0 并不存在,值为 undefined
- if(/^(\d{4})-(\d{2})-(\d{2})$/.test('2016-06-23')){
- console.log(RegExp.$1);//'2016'
- console.log(RegExp.$2);//'06'
- console.log(RegExp.$3);//'23'
- console.log(RegExp.$0);//undefined
- }
来源: http://www.phperz.com/article/17/0306/264616.html