正则

RegExp构造函数

  • 原来的有两种情况:
var regex = new RegExp('xyz', 'i');
// 等价于
var regex = /xyz/i;

var regex = new RegExp(/xyz/i);
// 等价于
var regex = /xyz/i;
//不允许
var regex = new RegExp(/xyz/, 'i');
//现在可以通过这种方式忽略
new RegExp(/abc/ig, 'i').flags

Unicode属性类:

\p{UnicodePropertyName=UnicodePropertyValue}匹配某一类字符,而\P实现反选,如:

// 匹配所有数字
const regex = /^\p{Number}+$/u;
regex.test('²³¹¼½¾') // true
regex.test('㉛㉜㉝') // true
regex.test('ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ') // true

具名组匹配

const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const matchObj = RE_DATE.exec('1999-12-31');//const year=matchObj[1];
const year = matchObj.groups.year; // 1999
const month = matchObj.groups.month; // 12
const day = matchObj.groups.day; // 31
//可以使用解构赋值方法直接匹配
let {groups: {one, two}} = /^(?<one>.*):(?<two>.*)$/u.exec('foo:bar');
one  // foo
two  // bar

//使用替换时,使用$<组名>
let re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
'2015-01-02'.replace(re, '$<day>/$<month>/$<year>')
// '02/01/2015'
//也可以是一个函数
'2015-01-02'.replace(re, (
   matched, // 整个匹配结果 2015-01-02
   capture1, // 第一个组匹配 2015
   capture2, // 第二个组匹配 01
   capture3, // 第三个组匹配 02
   position, // 匹配开始的位置 0
   S, // 原字符串 2015-01-02
   groups // 具名组构成的一个对象 {year, month, day}
 ) => {
 let {day, month, year} = groups;
 return `${day}/${month}/${year}`;
});
//在具名组内部使用某个具名组匹配,使用\k<祖名>,或者使用序号\1
const RE_TWICE = /^(?<word>[a-z]+)!\k<word>$/;
//const RE_TWICE = /^(?<word>[a-z]+)!\1$/;
RE_TWICE.test('abc!abc') // true
RE_TWICE.test('abc!ab') // false

正则匹配索引:

新提案:在exec()结果加上indices属性拿到开始和结束的位置

const text = 'zabbcdef';
const re = /ab/;
const result = re.exec(text);
result.index // 1
result.indices // [ [1, 3] ]
//使用group提供具名组匹配的开始和结束位置
const text = 'zabbcdef';
const re = /ab+(?<Z>cd)/;
const result = re.exec(text);
result.indices.groups // { Z: [ 4, 6 ] }

String.prototype.matchAll()

多个匹配结果经常使用g/y修饰符,逐一取出.

var regex = /t(e)(st(\d?))/g;
var string = 'test1test2test3';
var matches = [];
var match;
while (match = regex.exec(string)) {
  matches.push(match);
}
matches
// [
//   ["test1", "e", "st1", "1", index: 0, input: "test1test2test3"],
//   ["test2", "e", "st2", "2", index: 5, input: "test1test2test3"],
//   ["test3", "e", "st3", "3", index: 10, input: "test1test2test3"]
// ]

//或者使用matchAll(),返回的是遍历器
const string = 'test1test2test3';
// g 修饰符加不加都可以
const regex = /t(e)(st(\d?))/g;
for (const match of string.matchAll(regex)) {
  console.log(match);
}
// ["test1", "e", "st1", "1", index: 0, input: "test1test2test3"]
// ["test2", "e", "st2", "2", index: 5, input: "test1test2test3"]
// ["test3", "e", "st3", "3", index: 10, input: "test1test2test3"]
//遍历器转为数组
//1
[...string.matchAll(regx)]
//2
Array.from(string.matchAll(regex))

可以使用正则表达式的4个方法:
match(),replace(),search(),split()

u修饰符

Unicode模式用来正确处理码点大于0xFFFF的字符(4个字节),

/𠮷{2}/u.test('𠮷𠮷') // true
/^\S$/u.test('𠮷') // true,预定义模式,\S是预定义模式,匹配非空白字符
/^.$/u.test(s) // true,对.匹配
/\u{20BB7}/u.test('𠮷') // true,对于\u{}表示法
const r2 = /hello/u;//r2.unicode为true,可以看出使用了u修饰符。

y修饰符

y修饰符下一次匹配必须要在剩余串的第一个位置开始"粘连",

var s = 'aaa_aa_a';
var r1 = /a+/g;
var r2 = /a+/y;
r1.exec(s) // ["aaa"]
r2.exec(s) // ["aaa"]
r1.exec(s) // ["aa"]
r2.exec(s) // null
//使用lastIndex指定开始匹配位置
const REGEX = /a/g;
// 指定从2号位置(y)开始匹配
REGEX.lastIndex = 2;
// 匹配成功
const match = REGEX.exec('xaya');

y修饰符就是为了让头部匹配的标志^在全局中有效,

'a1a2a3'.match(/a\d/y) // ["a1"]
'a1a2a3'.match(/a\d/gy) // ["a1", "a2", "a3"]
//\s表示转移符号来匹配任何空白字符,注意y模式不忽略非法字符,而g模式忽略,可以通过正则结果的sticky是否为true来判断y修饰符,source返回正文,flags返回修饰符.
'a1a2a3'.match(/a\d/y) // ["a1"]
'a1a2a3'.match(/a\d/gy) // ["a1", "a2", "a3"]

dotAll模式即修饰符s

为了使用.匹配\n,使用s模式/foo.bar/s.test('foo\nbar') // true,可以通过.dotAll是否为true来判断。

后行断言

x在y前面才匹配,使用/x(?=y)/,x不在y前面匹配,使用/x(?!y),x在y后面才匹配,使用/(?<=y)x/,x不在y后面才匹配,使用/(?<!y)x/

posted @ 2022-10-16 09:35  梦呓qwq  阅读(9)  评论(0编辑  收藏  举报