正则表达式(RegExp)也称规则表达式(regular expression),是非常强大的字符串操作工具,语法格式为一组特殊字符构成的匹配模式,用来匹配字符串。ECMAScript 3以Perl为基础规范JavaScript正则表达式,实现Perl 5正则表达式的子集。JavaScript通过内置RegExp类型支持正则表达式,String和RegExp类型都提供执行正则表达式匹配操作的相关方法。
1、使用正则表达式
1.1、定义正则表达式
1.构造正则表达式
使用RegExp()构造函数可以定义正则表达式对象,具体语法格式如下:
new RegExp(pattern, attributes)
其中,参数pattern是一个字符串,指定匹配模式或者正则表达式对象;参数attributes是一个可选的修饰性标志,包含g、i和m,分别用来设置全局匹配、区分大小写的匹配和多行匹配。如果参数pattern是正则表达式对象,则必须省略第二个参数。
RegExp()函数将返回一个RegExp实例对象,对象包含指定的匹配模式和匹配标志。
RegExp()函数将返回一个RegExp实例对象,对象包含指定的匹配模式和匹配标志。
提示:JavaScript正则表达式支持g、i、m、u和y 5个标志符,简单说明如下:
- g:global缩写,定义全局匹配,正则表达式将在一行字符串范围内执行所有匹配。
- i:insensitive缩写,定义不区分大小写匹配,正则表达式忽视字母大小写。
- m:multiline缩写,定义多行字符串匹配。
- m:ES6新增,允许对于Unicode字符串进行匹配。
- y:ES6新增,开启黏滞模式匹配,允许设置匹配的精确位置。
【示例1】使用RegExp构造函数定义一个简单的正则表达式,希望匹配字符串中所有的字母a,不区分大小写,因此需要在第2个参数中设置g和i修饰词:
var r = new RegExp("a","gi"); //设置匹配模式为全局匹配,且不区分大小写var s = "JavaScript!=JAVA"; //字符串直接量var a = s.match(r); //匹配查找console.log(a); //返回数组["a","a","A","A"]
【示例2】在正则表达式中可以使用特殊字符。下面示例的正则表达式将匹配字符串“JavaScript JAVA”中每个单词的首字母:
var r = new RegExp("\\b\\w","gi"); //构造正则表达式对象var s = "JavaScript JAVA"; //字符串直接量var a = s.match(r); //匹配查找console.log(a); //返回数组["j", "J"]
在上面示例中,“\b"表示单词的边界,”\w"表示任意ASCII字符。由于在字符串中,反斜杠表示转义序列,为了避免误解,使用“\”替换所有“\”字符,使用双反斜杠表示斜杠自身。
2.正则表达式直接量
正则表达式直接量使用双斜杠作为分隔符进行定义,双斜杠之间包含的字符为正则表达式的字符模式,字符模式不能使用引号,标志字符放在最后一个斜杠的后面。其语法如下:
/pattern/attributes
【示例】定义一个正则表达式直接量,然后直接调用:
var r = /\b\w/gi;var s = "JavaScript JAVA";var a = s.match(r); //直接调用正则表达式直接量console.log(a); //返回数组["j", "J"]
提示:匹配模式不是字符串,对于RegExp()构造函数来说,它接收的参数全部是字符串,为了防止字符串被转义,需要使用双斜杠进行规避,而在正则表达式直接量中,每个字符都按正则表达式的语法规则定义,不需要考虑字符串的转义问题。
1.2、执行匹配
使用exec()方法可以执行通用匹配操作,具体语法格式如下:
regexp.exec(string)
regexp表示正则表达式对象,参数string是要检索的字符串。返回一个数组,其中存放匹配的结果。如果未找到匹配结果,则返回null。
数组的第1个元素存储匹配的字符串,第2个元素是第1个子表达式匹配的文本(如果有),第3个元素是第2个子表达式匹配的文本(如果有),以此类推。
数组对象还会包含下面两个属性:
- index:匹配文本的第一个字符的下标位置。
- input:存放被检索的字符串,即参数string自身。
提示:在非全局模式下,exec()方法返回的数组与String.match()方法返回的数组是相同的。
在全局模式下,exec()方法、String.match()方法返回结果不同。当调用exec()方法时,会为正则表达式对象定义lastIndex属性,指定执行下一次匹配的起始位置,同时返回匹配数组,与非全局模式下的数组结构相同;而String.match()方法仅返回匹配文本组成的数组,没有附加信息。
因此,在全局模式下获取完整的匹配信息只能使用exec()方法。
当exec()方法找到与表达式相匹配的文本后,会重置lastIndex属性为匹配文本的最后一个字符下标位置加1,为下一次匹配设置起始位置。因此,通过反复调用exec()方法,可以遍历字符串,实现全局匹配操作,如果找不到匹配文本,将返回null,并重置lastIndex属性为0。
【示例】定义正则表达式,然后调用exec()方法,逐个匹配字符串中每个字符,最后使用while语句显示完整的匹配信息:
var s = "JavaScript"; //测试使用的字符串直接量var r = /\w/g; //匹配模式while((a = r.exec(s)) ){ //循环执行匹配操作console.log("匹配文本 = " + a[0] + " a.index = " + a.index + " r.lastIndex = " + r.lastIndex); //显示每次匹配操作后返回的
数组信息}
在while语句中,把返回结果作为循环条件,当返回值为null时,说明字符串检测完毕,立即停止迭代,否则继续执行。在循环体内,读取返回数组a中包含的匹配结果,并读取结果数组的index属性,以及正则表达式对象的lastIndex属性,演示效果如下图所示:
注意:正则表达式对象的lastIndex属性是可读可写的。使用exec()方法对一个字符串执行匹配操作后,如果再对另一个字符串执行相同的匹配操作,应该手动重置lastIndex属性为0,否则不会从字符串的第一个字符开始匹配,返回的结果也会不同。