发布作者: JavaScript大王
百度收录: 正在检测是否收录...
最后更新: 2023年 01月 09日 16:34
作品采用: 《 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 》许可协议授权
/*
text:正则表达式规则的字符串
flag:修饰符
*/
let reg = new RegExp(text,flag);
// 或者直接传入一个正则对象
let reg1 = new RegExp(/xxx/g);
1.传入两个参数:
// 1.传入两个参数:一个字符串,一个修饰符字符
let reg1 = new RegExp("^[\u4e00-\u9fa5]{0,}$","g"); // 全局匹配,匹配所有汉字
2.传入一个参数:要注意,ES5语法中,此时不能传入第二个参数用于添加修饰符(会报错);
// 2.传入一个参数:该参数是正则表达式
let reg2 = new RegExp(/^[\u4e00-\u9fa5]{0,}$/g);
// =====>等价于:
let reg3 = /^[\u4e00-\u9fa5]{0,}$/g;
/*
第二种方式要注意:传入正则表达式对象时,不允许使用修饰符参数
*/
// ES6中,如果第一个参数是一个正则对象,此时也可用第二个参数指定修饰符,返回的新字符串以新修饰符为准
let reg4 = new RegExp(/^[\u4e00-\u9fa5]{0,}$/ig,'i');
console.log(reg4.flags); // i 返回的表达式修饰符以后指定的为准
1.match();
2.replace();
3.search();
4.split();
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]
// 字符串对象的原型对象方法调用了RegExp对象原型方法对应的方法; Symbol用于表示变量是独一无二的
修饰符 | 描述 |
---|---|
i | 匹配时忽略大小写 |
g | 全局匹配,查找所有匹配的字符 |
m | 多行匹配,查找满足边界字符^开头和$结尾的字符(每一行的开头和结尾) |
s | 默认情况的.是匹配除换行符之外的所有字符,加上s修饰符将包括换行符 |
1.点字符
默认情况的点字符是匹配除空格外的任意单个字符,==点字符处理大于0xFFFF的字符时,需要加上u字符才能识别Unicode字符==;
2.Unicode字符表示法
ES6新增了大括号表示Unicode字符的方法,==如果不加u修饰符,大括号会被当做量词==;
3.量词
使用u修饰符之后,==量词能正确识别大于0xFFFF的字符==;
4.预定义模式(\S....)
使用u修饰符之后,==预定义模式才能正确识别大于0xFFFF的unicode字符;
5.i修饰符
在某些情况下,仅仅使用i修饰符无法正确识别出非规范的字符,需要==i修饰符与u修饰符搭配使用==;
// y修饰符也是全局匹配,但是下一次匹配的结果必须是从上一次匹配成功的下一个位置开始的(所以叫粘连修饰符嘛嘿嘿)
const str = "aaa_aa_a";
let reg1 = /a+/g;
let reg2 = /a+/y;
// 在第一次匹配时,两个修饰符对应的表达式返回的结果是一样滴
let res1 = reg1.exec(str);
console.log(res1); // aaa
let res2 = reg2.exec(str);
console.log(res2); // aaa
// 第二次匹配:g修饰符能正确返回,但是y修饰符由于_的存在,上一次匹配的下一个位置无法匹配到满足条件的字符,所以返回null
let res3 = reg1.exec(str);
console.log(res3); // aa
let res4 = reg2.exec(str);
console.log(res4); // null
// sticky用于检测是否设置了y修饰符
const reg1 = /aaa/;
const reg2 = /aaa/y;
console.log(reg1.sticky); // false
console.log(reg2.sticky); // true
// sticky用于检测是否设置了y修饰符
const reg1 = /aaa/;
const reg2 = /aaa/y;
console.log(reg1.flags); // 啥也没返回
console.log(reg2.flags); // y
问题引入:.是一个特殊字符,表示任意的单个字符,但是行终止符除外,行终止符包括以下四个:
1.U+000A 换行符(\n);
2.U+000D 回车符(\r);
3.U+2028 行分隔符;
4.U+2029 段分隔符;
// 引入s修饰符,点能表示任意单个字符的模式就是dotAll模式
const reg1 = /peanut.run/;
const reg2 = /peanut.run/s;
const str = "peanut\nrun"
let res1 = reg1.test(str); // false 没有使用s修饰符,无法匹配换行符
let res2 = reg2.test(str); // true 使用s修饰符,点字符代表任意单个字符
// dotAll属性:正则表达式是否处于dotAll模式下
console.log(reg1.dotAll); // false
console.log(reg2.dotAll); // true
JavaScript只支持先行断言和先行否定断言,不支持后行断言和后行否定断言;
后行断言和后行否定断言是后引入的概念;
// 先行断言:x只有在y之前才匹配,必须写成/x(?=y)/的形式
const str = "我爱我你爱你";
// 找出爱字前面的我字
let reg = /我(?=爱)/;
let res1 = reg.exec(str); // 我 index=0
// 先行断言:x只有不在y前面才匹配,必须写成/x(?=y)/的形式
const str = "我爱我你爱你";
// 先行否定断言 x只有在y后面才匹配 必须写成/x(?!y)/的形式
// 找出我字后面的你字
let reg1 = /你(?!我)/;
let res2 = reg1.exec(str); // 你 index=3
// 后行断言:x只有在y后面才匹配 必须写成/(?<=y)x/的形式
const str1 = "好好学习学习";
let reg3 = /(?<=好)学/; // 只有在好字后面的才能匹配
let res3 = reg3.exec(str1); // 学 index=2
// 后行否定断言 x只有不在y后面才匹配(y前任意位置) 必须写成/(?<!y)x/的形式
const str2 = "1213"
let reg4 = /(?<!3)1/; // 匹配3前面的1
let res4 = reg4.exec(str2); // 1 index = 0 说明后行否定断言只要不再y之后,任意位置都可匹配
const regexGreekSymbol = /\p{Script=Greek}/u; // 匹配希腊文
regexGreekSymbol.test('π') // true
\p{UnicodePropertyName=UnicodePropertyValue}
const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/
const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/;
const matchObj = RE_DATE.exec("1997-08-06");
console.log(matchObj[1]); // 1997
console.log(matchObj[2]); // 08
console.log(matchObj[3]); // 06
// 具名组匹配,在组匹配时为每个组添加一个名字,便于在exec方法返回结果的groups
属性上根据组名引用对应的组
// “? + < + 组名 + >”的形式指定组名
const reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const matchObj1 = reg.exec("2020-12-21");
// 使用exec方法返回的groups属性通过组名可引用对应的匹配组
let year = matchObj1.groups.year; // 2020
let month = matchObj1.groups.month; // 12
let day = matchObj1.groups.day; // 21
// 可以通过具名组解构赋值,快捷的为变量赋值
const str = "2020-12-21";
let reg1 = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
let res1 = reg1.exec(str);
let {groups : {year,month,day}} = res1; // 先将groups对象赋值给前面的groups,再将groups中的每个属性依次赋值给对应的变量
console.log(year); // 2020
console.log(month); // 12
console.log(day); // 21
// 字符串替换时,可以使用$<组名>引用具名组
let re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
let res2 = '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}`;
});
const RE_TWICE = /^(?<word>[a-z]+)!\k<word>$/;
RE_TWICE.test('abc!abc') // true
RE_TWICE.test('abc!ab') // false
const RE_TWICE = /^(?<word>[a-z]+)!\1$/;
RE_TWICE.test('abc!abc') // true
RE_TWICE.test('abc!ab') // false
const RE_TWICE = /^(?<word>[a-z]+)!\k<word>!\1$/;
RE_TWICE.test('abc!abc!abc') // true
RE_TWICE.test('abc!abc!ab') // false
—— 评论区 ——