收录了这篇文章
1. JavaScript 正则表达式API 共有 6 个,字符串实例 4 个,正则实例 2 个:
String#search String#split String#match String#replace RegExp#test RegExp#exec
字符串对象正则方法
字符串对象共有 4 个方法,可以使用正则表达式:match()、replace()、search()和split()。
ES6 将这 4 个方法,在语言内部全部调用RegExp的实例方法,从而做到所有与正则相关的方法,全都定义在RegExp对象上。
String.prototype.match 调用 RegExp.prototype[Symbol.match] String.prototype.replace 调用 RegExp.prototype[Symbol.replace] String.prototype.search 调用 RegExp.prototype[Symbol.search] String.prototype.split 调用 RegExp.prototype[Symbol.split]
2. RegExp 构造函数
在 ES5 中,RegExp构造函数的参数有两种情况。
第一种情况是,参数是字符串,这时第二个参数表示正则表达式的修饰符(flag)。
var regex = new RegExp('xyz', 'i'); // 等价于 var regex = /xyz/i;
第二种情况是,参数是一个正则表示式,这时会返回一个原有正则表达式的拷贝。
var regex = new RegExp(/xyz/i); // 等价于 var regex = /xyz/i;
但是,ES5 不允许此时使用第二个参数添加修饰符,否则会报错。ES6 可以:
var regex = new RegExp(/xyz/, 'i'); new RegExp(/abc/ig, 'i').flags
上面代码中,原有正则对象的修饰符是ig,它会被第二个参数i覆盖。
3. 正则表达式的四种操作
正则表达式首先是“匹配”,有了匹配这一基本操作后,才有其他的操作:验证、切分、提取、替换。
3.1 验证
判断一个字符串中是否有数字
var regex = /\d/; var string = "abc123"; console.log( string.search(regex) ); console.log( regex.test(string) ); console.log( string.match(regex) ); // 输出 3 true [ '1', index: 3, input: 'abc123', groups: undefined ]
3.2 切分
“切分”,就是把目标字符串,切成一段一段的。在 JavaScript 中使用的是 split。 比如,目标字符串是 "html,css,javascript",按逗号来切分:
var regex = /,/; var string = "html,css,javascript"; console.log( string.split(regex) ); // => ["html", "css", "javascript"]
3.3 提取
虽然整体匹配上了,但有时需要提取部分匹配的数据。
此时正则通常要使用分组引用(分组捕获)功能,还需要配合使用相关 API。 这里,还是以日期为例,提取出年月日。注意下面正则中的括号:
//使用match: varregex = /^(\d{4})\D(\d{2})\D(\d{2})$/; varstring = "2017-06-26"; console.log(string.match(regex)); //=>["2017-06-26","2017","06","26",index:0,input:"2017-06-26"] //使用exec: varregex = /^(\d{4})\D(\d{2})\D(\d{2})$/; varstring = "2017-06-26"; console.log(regex.exec(string)); //=>["2017-06-26","2017","06","26",index:0,input:"2017-06-26"] //使用test: varregex = /^(\d{4})\D(\d{2})\D(\d{2})$/; varstring = "2017-06-26"; regex.test(string); console.log(RegExp.$1, RegExp.$2, RegExp.$3); //=>"2017""06""26" //使用search: varregex = /^(\d{4})\D(\d{2})\D(\d{2})$/; varstring = "2017-06-26"; string.search(regex); console.log(RegExp.$1, RegExp.$2, RegExp.$3); //=>"2017""06""26" //使用replace: varregex = /^(\d{4})\D(\d{2})\D(\d{2})$/; varstring = "2017-06-26"; vardate = []; string.replace(regex, function (match, year, month, day) { date.push(year, month, day); }); console.log(date); //=>["2017","06","26"]
其中,最常用的是 match。
3.4 替换
找,往往不是目的,通常下一步是为了替换。在 JavaScript 中,使用 replace 进行替换。 比如把日期格式,从 yyyy-mm-dd 替换成 yyyy/mm/dd:
var string = "2017-06-26"; string.replace(/-/g, "/") console.log( today ); // => 2017/06/26
这里只是简单地应用了一下 replace。但,replace 方法很是强大的,是需要重点掌握的。
4. 函数详解
4.1 search 函数
var string = "2017.06.27"; console.log( string.search(".") ); // => 0 //需要修改成下列形式之一 console.log( string.search("\\.") ); console.log( string.search(/\./) ); // => 4 // => 4
4.2 match函数
match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。
该方法类似 indexOf() 和 lastIndexOf(),但是它返回指定的值,而不是字符串的位置。
语法
stringObject.match(searchvalue)
stringObject.match(regexp)
searchvalue 必需。规定要检索的字符串值。
regexp 必需。规定要匹配的模式的 RegExp 对象。如果该参数不是 RegExp 对象,则需要首先把它传递给 RegExp 构造函数,将其转换为 RegExp 对象。
返回值
match 返回结果的格式,与正则对象是否有修饰符 g 有关。
var string = "2017.06.27"; var regex1 = /\b(\d+)\b/; var regex2 = /\b(\d+)\b/g; console.log( string.match(regex1) ); console.log( string.match(regex2) ); // => ["2017", "2017", index: 0, input: "2017.06.27"] // => ["2017", "06", "27"]
如果没有标志 g,那么 match() 方法就只执行一次匹配。
如果没有找到任何匹配的文本, match() 将返回 null。
如果匹配到,会返回一个数组。该数组的第 0 个元素存放的是匹配文本,而其余的元素存放的是与正则表达式的子表达式匹配的文本。index 是匹配文本的起始字符的位置,input 是被搜索字符串。
4.3 exec函数
当正则没有 g 时,使用 match 返回的信息比较多。但是有 g 后,就没有关键的信息 index 了。
而 exec 方法就能解决这个问题,它能接着上一次匹配后继续匹配:
var string = "2017.06.27"; var regex2 = /\b(\d+)\b/g; console.log( regex2.exec(string) ); console.log( regex2.lastIndex); console.log( regex2.exec(string) ); console.log( regex2.lastIndex); console.log( regex2.exec(string) ); console.log( regex2.lastIndex); console.log( regex2.exec(string) ); console.log( regex2.lastIndex); // => ["2017", "2017", index: 0, input: "2017.06.27"] // => 4 // => ["06", "06", index: 5, input: "2017.06.27"] // => 7 // => ["27", "27", index: 8, input: "2017.06.27"] // => 10 // => null // => 0
其中正则实例 lastIndex 属性,表示下一次匹配开始的位置。
比如第一次匹配了 "2017",开始下标是 0,共 4 个字符,因此这次匹配结束的位置是 3,下一次开始匹配
的位置是 4。
从上述代码看出,在使用 exec 时,经常需要配合使用 while 循环:
var string = "2017.06.27"; var regex2 = /\b(\d+)\b/g; var result; while ( result = regex2.exec(string) ) { console.log( result, regex2.lastIndex ); } // => ["2017", "2017", index: 0, input: "2017.06.27"] 4 // => ["06", "06", index: 5, input: "2017.06.27"] 7 // => ["27", "27", index: 8, input: "2017.06.27"] 10
4.4 test函数
上面提到了正则实例的 lastIndex 属性,表示尝试匹配时,从字符串的 lastIndex 位开始去匹配。
字符串的四个方法,每次匹配时,都是从 0 开始的,即 lastIndex 属性始终不变。
而正则实例的两个方法 exec、test,当正则是全局匹配时,每一次匹配完成后,都会修改 lastIndex。下面 让我们以 test 为例,看看你是否会迷糊:
var regex = /a/g; console.log( regex.test("a"), regex.lastIndex ); console.log( regex.test("aba"), regex.lastIndex ); console.log( regex.test("ababc"), regex.lastIndex ); // => true 1 // => true 3 // => false 0
注意上面代码中的第三次调用 test,因为这一次尝试匹配,开始从下标 lastIndex,即 3 位置处开始查 找,自然就找不到了。
如果没有 g,自然都是从字符串第 0 个字符处开始尝试匹配:
var regex = /a/; console.log( regex.test("a"), regex.lastIndex ); console.log( regex.test("aba"), regex.lastIndex ); console.log( regex.test("ababc"), regex.lastIndex ); // => true 0 // => true 0 // => true 0
test 整体匹配时需要使用 ^ 和 $,如果,要整体匹配,正则前后需要添加开头和结尾:
console.log( /123/.test("a123b") ); // => true console.log( /^123$/.test("a123b") ); // => false console.log( /^123$/.test("123") ); // => true
参考:《JavaScript正则表达式迷你书》 《ES6 标准入门》
修改时间 2021-12-23