正则表达式
正则表达式
正则表达式(regularexpression)描述了一种字符串匹配的模式(pattern),可以用来检查一个串是 否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。
1正则表达式基本介绍
JavaScript中的正则表达式用RegExp对象表示,有两种写法:一种是字面量写法;另一种是构造 函数写法
字面量写法
正则表达式字面量写法,又叫Perl写法,因为JavaScript的正则表达式特性借鉴自Perl。正则表达 式字面量定义为包含在一对斜杠/之间的字符,并且可以有3个模式修正符
let expression = /pattern/flags;
这里的patte rn就是指我们的字符串模式,而后面的flags则是指带的模式修正符。 JavaScript中的正则表达式支持下列3个模式修正符:
g:表示全局(global)模式,即模式将被应用于所有字符串,而并非在发现第一个匹配项时立即停 止
i:表示不区分大小写(case-insensitive)模式,即在确定匹配项时忽略模式与字符串的大小写
m:表示多行(multiline)模式,即在到达一行文本末尾时还会继续查找下一行中是否存在与模式匹 配的项
RegExp构造函数
和普通的内置对象一样,RegExp正则表达式对象也支持new RegExp。构造函数的形式来创建正 则。RegExp构造函数接收两个参数:要匹配的字符串模式(pattern)和可选的模式修正符(flags)。
let reg1 = /at/i;
//等同于
let reg2 = new RegExp("at","i");
需要注意无论是字面量,还是构造函数,返回的类型都为object
let reg1 = /at/i;
//等同于
let reg2 = new RegExp("at","i");
console.log(typeof reg1);//object
console.log(typeof reg2);//object
字面量构建的正则表达式,那么大致可以分为4个部分:定界符,简单字符, 元字符和模式修正符。而如果是构造函数构建的正则表达式,则少了一个定界符,由简单字符, 元字符以及模式修正符组成。
简单字符在正则表达式中,就是字面的含义,比如/a/匹配a, /b/匹配b,这样的字符被称之为简 单字符,示例如下:
let reg = /dog/;
let str = "This is a big dog"; console.log(reg.test(str));//true
这里我们调用了正则表达式的实例方法test(),该方法如果和传入的字符串能够匹配,则返回 true,否则返回false。
除了简单字符以外,还有一些字符,它们除了字面意思外,还有着特殊的含义,这些字符就是元字符。
元字符 |
名称 |
匹配对象 |
. |
点号 |
单个任意字符(除回车\r、换行\n、行分隔符\u2028和段分隔符\U2029外) |
[] |
字符组 |
列出的单个任意字符 |
e |
排除型字符 组 |
未列出的单个任意字符 |
? |
问号 |
匹配0次或1次 |
* |
星号 |
匹配0交或多次 |
+ |
加号 |
匹配1次或多次 |
{a,b} |
区间量词 |
匹配至少a次,最多b次 |
^
|
脱字符 |
行的起始位置 |
$ |
美元符 |
行的结束位置 |
| |
竖线 |
分隔两边的任意一个表达式 |
() |
括号 |
限制多选结构的范围,标注量词作用的元素,为反向引用捕获 文本 |
转义字符
转义字符(escape)表示为反斜线\ +字符的形式,共有以下3种情况
1.因为元字符有特殊的含义,所以无法直接匹配。如果要匹配它们本身,则需要在它们前面加上 反斜杠\
console.log(/1+1/.test("1+1"));//false console.log(/1\+1/.test("1+1"));//true
但实际上,并非14个元字符都需要转义,右方括号]和右花括号}可以不用写转义字符,当然写了 也不会算你错
console.log(/]/.test("]"));//true console.log(/\]/.test("]"));//true
2.\加非元字符,表示一些不能打印的特殊字符,具体如下表:
符号 含义
\0 NUL 字符 \uOOOO
[\b] 匹配退格符\u0008,不要与\b混淆
\t 制表符\u0009
\n 换行符\u000A
\v 垂直制表符\u000B
\f 换页符\u000C
\r 回车符\u000D
\xnn 由十六进制数nn指定的拉丁字符
\uxxxx 由十六进制数xxxx指定的Unicode字符(\u4e00-\u9fa5代表中文)
\cX 控制字符X,表示ctrl-[X],其中的X是A-Z之中任一个英文字母,用来匹配控制字符
3. \加任意其他字符,默认情况就是匹配此字符,也就是说,反斜线\被忽略了
console.log(/\x/.test("x"));//true console.log(/\yat/.test("yat"));//true
2字符组相关元字符
- 字符组介绍
字符组(Character Class),有的翻译成字符类或字符集。简单而言,就是指用方括号表示的一组 字符,它匹配若干字符之一
//匹配0-9这10个数字之一
let reg = /[0123456789]/;
console.log(reg.test("1"));//true
console.log(reg.test("a"));//false
注意:字符组中的字符排列顺序并不影响字符组的功能,出现重复字符也不会影响
[0123456789]
//等价于
[9876543210]
//等价于
[1234567890123456789]
2.范围
正则表达式通过连字符-提供了范围表示法,可以简化字符组
[0123456789]
//等价于
[0-9] [abcdefghijklmnopqrstuvwxyz]
//等价于
[a-z]
连字符-表示的范围是根据ASCI I编码的码值来确定的,码值小的在前,码值大的在后 所以[0-9 ]是合法的,而[9-0]会报错
//匹配0-9这10个数字之一
let reg1 = /[0-9]/; console.log(reg1.test("1"));//true
let reg2 = /[9-0]/;//报错
console.log(reg2.test("1"));
//SyntaxError: Invalid regular expression/[9-0]/:
//Range out of order in character class
在字符组中可以同时并列多个-范围
//[0—9a—zA—Z];匹配数字、大写字母和小写字母
//[0-9a-fA-F];匹配数字,大、小写形式的a-f,用来验证十六进制字符 console.log(/[0-9a-fA-F]/.test('d'));//true
console.log(/[0-9a-fA-F]/.test('x'));//false
只有在字符组内部,连字符-才是元字符,表示一个范围,否则它就只能匹配普通的连字符号。 注意:如果连字符出现在字符组的开头或末尾,它表示的也是普通的连字符号,而不是一个范围
//匹配中划线
console.log(/-/.test('-'));//true console.log(/[-]/.test('-'));//true
//匹配0-9的数字或中划线
console.log(/[0-9]/.test('-'));//false console.log(/[0-9-]/.test('-'));//true
console.log(/[0-9\-]/.test('-'));//true
console.log(/[-0-9]/.test('-'));//true console.log(/[\-0-9]/.test('-'));//true
3.排除
字符组的另一个类型是排除型字符组,在左方括号后紧跟一个脱字符八表示,表示在当前位置匹配一个没有列出的字符,所以[入0-9]表示0-9以外的字符
/匹配第一个是数字字符,第二个不是数字字符的字符串
console.log(/[0-9][^0-9]/.test('1e'));//true
console.log(/[0-9][^0-9]/.test('q2'));//false
注意:在字符组内部,脱字符八表示排除,而在字符组外部,脱字符八表示一个行锚点
八符号是元字符,在字符组中只要八符号不挨着左方括号就可以表示其本身含义,不转义也可 以
//匹配abc和^符号
console.log(/[a-c^]/.test('^'));//true console.log(/[a-c\^]/.test('^'));//true console.log(/[\^a-c]/.test('^'));//true
在字符组中,只有人-[]这4个字符可能被当做元字符,其他有元字符功能的字符都只表示其本 身,示例如下:在[]中的* + ?等元字符都是被当作其本身
//部分元字符示例
//这里会被当作是字面意思
console.log(/[1$]/.test('$')); //true
console.log(/[1|2]/.test('|')); //true
console.log(/[1?]/.test('?')); //true
console.log(/[1*]/.test('*')); //true
console.log(/[1+]/.test('+')); //true
console.log(/[1.]/.test('.')); //true
4.简记
用[0-9]、[a-z]等字符组,可以很方便地表示数字字符和小写字母字符。对于这类常用字符组,正 则表达式提供了更简单的记法,这就是字符组简记(shorthands)
常见的字符组简记有\d、\w、\s。其中d表示(digit)数字,w表示(word)单词,s表示(space) 空白
正则表达式也提供了对应排除型字符组的简记法:\D、\W、\S。字母完全相同,只是改为大 写。它们和小写的简记符在含义上刚好相反。
\d 数字,等同于[0-9]
\D 非数字,等同于[八0-9]
\s 空白字符,等同于[\f\n\r\t\u000B\u0020\u00A0\u2028\u2029]
\S 非空白字符,等同于[入\f\n\r\t\u000B\u0020\u00A0\u2028\u2029]
\w 字母、数字、下划线,等同于[0-9A-Za-z_](汉字不属于\w)
\W 非字母、数字、下划线,等同于[八0-9A-Za-z_]
注意:\w不仅包括字母、数字,还包括下划线。在进行数字验证时,只允许输入字母和数字 时,不可以使用\w,因为还包含了下划线。所以应该使用[0-9a-zA-Z]
5.任意字符
经常有人有一个误区就是认为点可以代表任意字符,其实并不是。点号.代表除回车(V),换行 (\n),行分隔符22028)和段分隔符(\u2029)以外的任意字符。
妥善的利用互补属性,可以得到一些巧妙的效果。比如,[\s\S]、[\w\W]、[\d\D]都可以表示任意字符
//匹配任意字符
console.log(/./.test('\r'));//false
console.log(/[\s\S]/.test('\r'));//true
console.log(/[\d\D]/.test('\r'));//true
3量词相关元字符
据字符组的介绍,可以用字符组[0-9]或\d来匹配单个数字字符,如果用正则表达式表示更复杂 的字符串,则不太方便
//表示邮政编码6位数字
/[0-9][0-9][0-9][0-9][0-9][0-9]/;
//等价于
/\d\d\d\d\d\d/;
正则表达式提供了量词,用来设定某个模式出现的次数
{n} 匹配n次
{n,m} 匹配至少n次,最多m次
{n,} 匹配至少n次
? 相当于{0,1}
* 相当于{0,}
+ 相当于{1,}
美国英语和英国英语有些词的写法不一样,如果traveler和traveller, favor和favour, color和 colour
//同时匹配美国英语和英国英语单词
/travell?er/;
/favou?r
/colou?r/;
协议名有http和https两种
/https?/;
贪婪模式(扩展)
默认情况下,量词都是贪婪模式(greedy quantifier),即匹配到下一个字符不满足匹配规则为止
let reg = /a+/;
let str = "aaabbcc";
console.log(reg.exec(str));
//[ 'aaa', index: 0, input: 'aaabbcc' ]
这里我们使用了正则表达式的另外一个常用的实例方法exec()。该方法会返回一个数组,数组 里面有匹配上的字符,匹配上的索引值以及原始的字符串等更加详细的信息。
懒惰模式(扩展)
懒惰模式(lazy quantifier)和贪婪模式相对应,在量词后加问号?表示,表示尽可能少的匹配,一 旦条件满足就再不往下匹配
{n}? |
匹配n次 |
{n,m}? |
匹配至少n次,最多m次 |
{n,}? |
匹配至少n次 |
?? |
相当于{0,1} |
*? |
相当于{0,} |
+? |
相当于{1,} |
示例如下:
let reg = /a+?/;
let str = "aaabbcc";
console.log(reg.exec(str));
//[ 'a', index: 0, input: 'aaabbcc' ]
4括号相关元字符
括号有两个功能,分别是分组和引用。具体而言,用于限定量词或选择项的作用范围,也可以用 于捕获文本并进行引用或反向引用
分组
量词控制之前元素的出现次数,而这个元素可能是一个字符,也可能是一个字符组,也可以是一 个表达式。如果把一个表达式用括号包围起来,这个元素就是括号里的表达式,被称为子表达式 如果希望字符串"ab"重复出现2次,应该写为(ab){2},而如果写为ab{2},则{2}只限定b,如下:
console.log(/ab{2}/.test("abab"));//false console.log(/(ab){2}/.test("abab"));//true
身份证长度有15位和18位两种,如果只匹配长度,可能会想当然地写成\d{15,18},实际上这是 错误的,因为它包括15、16、17、18这四种长度。因此,正确的写法应该是
/\d{15}(\d{3})?/
捕获
括号不仅可以对元素进行分组,还会保存每个分组匹配的文本,等到匹配完成后,引用捕获的内 容。因为捕获了文本,这种功能叫捕获分组
比如,要匹配诸如2016-06-23这样的日期字符串
/(\d{4})-(\d{2})-(\d{2})/
与以往不同的是,年、月、日这三个数值被括号括起来了,从左到右为第1个括号、第2个括号和 第3个括号,分别代表第1、2、3个捕获组。ES有9个用于存储捕获组的构造函数属性,如果使用 的是test()方法,那么通过正则对象的$1-$9属性可以访问到
//RegExp.$1\RegExp.$2\RegExp.$3....”至0RegExp.$9
//分别用于存储第一、第二”.”第九个匹配的捕获组。
//在调用exec()或test()方法时,这些属性会被自动填充 console.log(/(\d{4})-(\d{2})-(\d{2})/.test('2016-06-23'));//true
console.log(RegExp.$1);//2016
console.log(RegExp.$2);//06
console.log(RegExp.$3);//23
console.log(RegExp.$4);// " "
再例如:
let reg = /(a+)(b*)xj/;
let str = "aabbbxj"; console.log(reg.test(str));//true
console.log("$ 1 的值:",RegExp.$1);//$1 的值:aa console.log("$2的值:",RegExp.$2);//$2的值:bbb
console.log("$3 的值:",RegExp.$3);//$3 的值:
而exec()方法是专门为捕获组而设计的,返回的数组中,第一项是与整个模式匹配的字符串, 其他项是与模式中的捕获组匹配的字符串,如果要获取,那么可以通过指定数组的下标来进行获 取,如下:
let reg = /(\d{4})-(\d{2})-(\d{2})/;
let str = "2017-03-21";
let i = reg.exec(str);
console.log(i);
//[ '2017-03-21', '2017', '03', '21', index: 0, input: '2017-03-21' ] console.log(i[1]);//2017
console.log(i[2]);//03
console.log(i[3]);//21
捕获分组捕获的文本,不仅可以用于数据提取,也可以用于替换
字符串的replaced方法就是用于进行数据替换的,该方法接收两个参数,第一个参数为待查 找的内容,而第二个参数为替换的内容
let str = "2017-12-12";
console.log(str.replace(/-/g,"."));
//2017.12.12
注意这里书写正则表达式的时候必须要写上模式修正符g,这样才能够进行全局匹配。 在replace()方法中也可以引用分组,形式还是用$num,其中num是对应分组的编号
//把2017-03-23的形式变成03-23-2017
let reg = /(\d{4})-(\d{2})-(\d{2})/;
let str = "2017-03-23"; console.log(str.replace(reg,"$2-$3-$1"));
//03-23-2017
5选择相关元字符
竖线|在正则表达式中表示或(OR)关系的选择,以竖线|分隔开的多个子表达式也叫选择分支 或选择项。在一个选择结构中,选择分支的数目没有限制。
在选择结构中,竖线|用来分隔选择项,而括号()用来规定整个选择结构的范围。如果没有出
现括号,则将整个表达式视为一个选择结构。
选择项的尝试匹配次序是从左到右,直到发现了匹配项,如果某个选择项匹配就忽略右侧其他选 择项,如果所有子选择项都不匹配,则整个选择结构匹配失败。
console.log(/12|23|34/.exec('1'));//null
console.log(/12|23|34/.exec('12'));//[ '12', index: 0, input: '12' ]
console.log(/12|23|34/.exec('23'));//[ '23', index: 0, input: '23' ] console.log(/12|23|34/.exec('2334'));//[ '23', index: 0, input: '2334' ]
在选择结构中,应该尽量避免选择分支中存在重复匹配,因为这样会大大增加回溯的计算量
//不良的选择结构
a|[ab]
[0-9]|\w
6断言相关元字符(扩展)
在正则表达式中,有些结构并不真正匹配文本,而只负责判断在某个位置左/右侧是否符合要 求,这种结构被称为断言(assertion),也称为锚点(anchor),常见的断言有3种:单词边界、行开 头结尾、环视
7模式修正符
匹配模式(match mode)又被称之为模式修正符。指的是匹配时使用的规则。设置特定的模式,可 能会改变对正则表达式的识别。前面已经介绍过创建正则表达式对象时,可以设
置m、i、g这三个标志,分别对应多行模式、不区分大小模式和全局模式三种
默认地,正则表达式是区分大小写的,通过设置标志'i',可以忽略大小写(ignore case)
console.log(/ab/.test("aB"));//false
console.log(/ab/i.test("aB"));//true
m
默认地,正则表达式中的八和$匹配的是整个字符串的起始位置和结束位置,而通过设置标 志'm',开启多行模式,它们也能匹配字符串内部某一行文本的起始位置和结束位置
console.log(/^b/.test('a\nb')); //false
console.log(/^b/m.test('a\nb')); //true
g
默认地,第一次匹配成功后,正则对象就停止向下匹配了。g修饰符表示全局匹配(global),设 置'g'标志后,正则对象将匹配全部符合条件的结果,主要用于搜索和替换
console.log('1a,2a,3a'.replace(/a/,'b')); //1b,2a,3a
console.log('1a,2a,3a'.replace(/a/g,'b')); //1b,2b,3b
8优先级
正则表达式千变万化,但是大多都是由之前介绍过的字符组、括号、量词等基本结构组合而成的。这些元字符,和运算符一样拥有一个优先级关系,如下:
//从上到下,优先级逐渐降低
\ 转移符
() (?!) (?=) [ ] 括号、字符组、环视
* + ? {n} {n,} {n,m} 量词
^ $ 起始结束位置
| 选择
由于括号的用途之一就是为量词限定作用范围,所以优先级比量词高
console.log(/ab{2}/.test('abab'));//false console.log(/(ab){2}/.test('abab'));//true
|注意:选择符|的优先级最低,比起始和结束位置都要低
console.logWb|cd$/.test('abc' ));//true
console.log(/入(ab|cd)$/.test('abc'));//false
console.log(/入(ab|cd)$/.test('ab'));//true
console.log(/入(ab|cd)$/.test('cd'));//true
9局限性
尽管JavaScript中的正则表达式功能比较完备,但与其他语言相比,缺少某些特性
下面列出了 JavaScript正则表达式不支持的特性
・POSIX字符组(只支持普通字符组和排除型字符组)
・ Unicode支持(只支持单个Unicode字符)
・匹配字符串开始和结尾的\AW\Z锚(只支持和$)
・逆序环视(只支持顺序环视)
・命名分组(只支持0-9编号的捕获组)
・单行模式和注释模式(只支持m、i、g)
・模式作用范围
・纯文本模式
10正则表达式属性和方法
前面有提到,当我们使用typeof运算符来打印正则表达式的类型时,返回的是object ,这说 明正则表达式在JavaScript中也是一种对象。那么既然是对象,就应该有相应的属性和方法。
- 实例属性
每个RegExp实例对象都包含如下5个属性
- global:布尔值,表示是否设置了g标志
- ignoreCase:布尔值,表示是否设置了 i标志
- IastIndex:整数,表示开始搜索下一个匹配项的字符位置,从0算起
- multiline:布尔值,表示是否设置了标志m
- source:正则表达式的字符串表示,按照字面量形式而非传入构造函数中的字符串模式返回
示例如下:
let reg = /test/gi;
console.log(reg.global);//true
console.log(reg.ignoreCase);//true
console.log(reg.multiline);//false
console.log(reg.lastIndex);//0
console.log(reg.source);//test
如果使用RegExp的exec()或test()函数,并且设定了全局模式g ,正则表达式的匹配就会 从lastindex的位置开始,并且在每次匹配成功之后重新设定lastindex ,继续往后匹配。 这样,就可以在字符串中重复迭代,依次寻找各个匹配结果。但是,如果需要对不同字符串调用 同一个RegExp的exec()或test()方法,这个变量也可能会带来意料之外的匹配结果,所以在更换字符串时,要显式地将RegExp的lastindex置为0
//exec()方法以数组形式返回匹配项
var reg = /\w/g;
var str = "abcd";
console.log(reg.lastIndex);//0
console.log(reg.exec(str));//[ 'a', index: 0, input: 'abcd' ]
console.log(reg.lastIndex);//1
console.log(reg.exec(str));//[ 'b', index: 1, input: 'abcd' ]
console.log(reg.lastIndex);//2
console.log(reg.exec(str));//[ 'c', index: 2, input: 'abcd' ]
console.log(reg.lastIndex);//3
console.log(reg.exec(str));//[ 'd', index: 3, input: 'abcd' ]
console.log(reg.lastIndex);//4
console.log(reg.exec(str));//null
console.log(reg.lastIndex);//0
console.log(reg.exec(str));//[ 'a', index: 0, input: 'abcd' ]
2.构造函数属性(扩展)
RegExp构造函数属性被看成静态属性,这些属性基于所执行的最近一次正则表达式操作而变化 有两种方式访问它们,即长属性名和短属性名。短属性名大都不是有效的ECMAScript标识符, 所以必须通过方括号语法来访问
长属性名 |
短属性名 |
说明 |
input |
$_ |
最近一次要匹配的字符串 |
lastMatch |
$& |
最近一次的匹配项 |
lastParen |
$+ |
最近一次匹配的捕获组 |
leftContext |
$` |
input字符串中l astMatch之前的文本 |
multiline |
$* |
布尔值,表示是否所有表达式都使用多行模式 |
rightContext |
$’ |
input字符串中l astMatch之后的文本 |
使用这些属性,可以从exec()方法或test()方法执行的操作中提取出更具体的信息
3.实例方法
RegExp对象的实例方法共5个,分为两类。包括 toString()、toLocalString()、valueOf()这3种对象通用方法和test()、exec()这2种正则匹配方法
对象通用方法(扩展)
RegExp对象继承了Object对象的通用方法 toString()、toLocaleString()、valueOf()这 三个方法
- toString(): toString()方法返回正则表达式的字面量
- toLocaleString(): toLocaleString()方法返回正则表达式的字面量
- valueOf(): valueOf()方法返回返回正则表达式对象本身
注意:不论正则表达式的创建方式是哪种,这三个方法都只返回其字面量形式
let pattern1 = new RegExp('[bc]at','gi');
console.log(pattern1.toString()); // '/[bc]at/gi'
console.log(pattern1.toLocaleString()); // '/[bc]at/gi'
console.log(pattern1.valueOf()); // /[bc]at/gilet pattern2 = /[bc]at/gi;
console.log(pattern2.toString()); // '/[bc]at/gi'
console.log(pattern2.toLocaleString()); // '[bc]at/gi'
console.log(pattern2.valueOf()); // /[bc]at/gi
正则匹配方法
正则表达式RegExp对象的正则匹配方法只有两个:分别是test()和exec()
test()
test()方法用来测试正则表达式能否在字符串中找到匹配文本,接收一个字符串参数,匹配时 返回true,否则返回false
let reg = /test/;
let str = "this is a test"; console.log(reg.test(str));//true
在调用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
前面有介绍过,JS有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
}
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);
// /mom( and dad( and baby)?)?/gi [ 'mom and dad and baby',
// ' and dad and baby',
// ' and baby',
// index: 0,
// input: 'mom and dad and baby and others' ]
对于exec()方法而言,即使在模式中设置了全局标志g ,它每次也只会返回一个匹配项。在不 设置全局标志的情况下,在同一个字符串上多次调用exec(),将始终返回第一个匹配项的信息
var text = 'cat,bat,sat,fat';
var pattern1 = /.at/;
var matches = pattern1.exec(text);
console.log(pattern1,matches);
///.at/ [ 'cat', index: 0, input: 'cat,bat,sat,fat' ]
var text = 'cat,bat,sat,fat';
matches = pattern1.exec(text);
console.log(pattern1,matches);
///.at/ [ 'cat', index: 0, input: 'cat,bat,sat,fat' ]
而在设置全局标志的情况下,每次调用exec()都会在字符串中继续查找新匹配项
var text = 'cat,bat,sat,fat';
var pattern2 = /.at/g;
var matches = pattern2.exec(text);
console.log(pattern2,matches);
///.at/g [ 'cat', index: 0, input: 'cat,bat,sat,fat' ]
var text = 'cat,bat,sat,fat';
matches = pattern2.exec(text);
console.log(pattern2,matches);
///.at/g [ 'bat', index: 4, input: 'cat,bat,sat,fat' ]
注意:用exec()方法找出匹配的所有位置和所有值
var string = 'j1h342jg24g234j 3g24j1';
var pattern = /\d/g;
var valueArray = [ ];//值
var indexA rray = [ ];//位置
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);