本文是 重温基础 系列文章的第九篇。 今日感受:时间管理-角色管理法。系列目录:【复习资料】ES6/ES7/ES8/ES9资料整理(个人整理)【重温基础】1.语法和数据类型【重温基础】2.流程控制和错误处理【重温基础】3.循环和迭代【重温基础】4.函数【重温基础】5.表达式和运算符【重温基础】6.数字【重温基础】7.时间对象【重温基础】8.字符串本章节复习的是JS中的正则表达式,JS中用来匹配字符串的强大工具。 前置知识: JS中的正则表达式是用来匹配字符串中指定字符组合的模式。 另外需要记住:正则表达式也是对象。1.创建正则表达式使用一个正则表达式字面量:let reg = /ab+c/;let reg = /^[a-zA-z]/gi;使用RegExp对象:new RegExp(str[, attr])接收2个参数,str是一个字符串,指定正则表达式匹配规则,attr可选,表示匹配模式,值有g(全局匹配),i(区分大小写的匹配)和m(多行匹配)。let reg = new RegExp(‘ab+c’);let reg = new RegExp(/^[a-zA-z]/, “gi”);let reg = new RegExp("^[a-zA-z]", “gi”);正则表达式的返回值,是一个新的RegExp对象,具有指定的模式和标志。 返回信息介绍:对象属性描述案例中对应的值reglastIndex下一个匹配的索引(仅在使用g参数时可用)0regsource模式文本。在正则表达式创建时更新,不执行。“ab+c"regignoreCase是否使用了 “i” 标记使正则匹配忽略大小写。trueregglobal是否使用了 “g” 标记来进行全局的匹配。trueregmultiline是否使用了 “m” 标记使正则工作在多行模式。false关于正则表达式的一些方法属性,文章后面介绍,这里先复习定义和使用。2.使用正则表达式JS的正则表达式可以被用于:RegExp对象的exec和test方法;String对象的match、replace、search和split方法。2.1 RegExp对象方法方法介绍exec检索字符串中指定的值。返回找到的值,并确定其位置。test检索字符串中指定的值。返回 true 或 false。2.1.1 exec(str)str: 需要检索的字符串。 若检索成功,返回匹配的数组,否则返回null。let str = “hello leo!";let reg = new RegExp(“leo”, “g”);let result = reg.exec(str);// 也可以写成let result = /leo/g.exec(“hello leo!”);/[ 0: “leo”, groups: undefined, index: 6, input: “hello leo!”, length: 1]/let result2 = /(leo \S)/g.exec(“hello leo hi leo!”);/* 0: “leo hi” 1: “leo hi” 2: “hi” groups: undefined index: 6 input: “hello leo hi leo!” length: 3*/返回信息介绍:对象属性描述案例中对应的值result[0]匹配到的所有字符串"leo"resultinput初始字符串。“hello leo!“resultindex在输入的字符串中匹配到的以0开始的索引值。6result2[1],…,[n]括号中的分组捕获[1]=> “leo hi”;[2] => “hi"2.1.2 test(str)str:需要检索的字符串。 若匹配成功返回true否则false。 等价于 reg.exec(str) != null。let str = “hello leo!";let res = /^leo/.test(str); // faslelet res1 = /^leo/.test(str); // true^str表示匹配以str开头的字符串,这些符号文章后面会介绍。2.2 String对象方法方法介绍search检索与正则表达式相匹配的值。match找到一个或多个正则表达式的匹配。replace替换与正则表达式匹配的子串。split把字符串分割为字符串数组。2.2.1 searchstr.search(reg): str:被检索的源字符串。 reg:可以是需要检索的字符串,也可以是需要检索的RegExp对象,可以添加标志,如i。 若检索成功,返回第一个与RegExp对象匹配的字符串的起始位置,否则返回-1。let str = “hello leo!";let res = str.search(/leo/g); // 6let str1 = “hello leoleoleoleo!";let res1 = str.search(/leo/g); // 6let res2 = str.search(/pingan/g); // -12.2.2 matchstr.match(reg): str:被检索的源字符串。 reg:可以是需要检索的字符串,也可以是需要检索的RegExp对象,可以添加标志,如i。 若检索成功,返回与reg匹配的所有结果的一个数组,数组的第一项是进行匹配完整的字符串,之后的项是用圆括号捕获的结果,否则返回null。let str = ‘For more information, see Chapter 3.4.5.1’;let reg = /see (chapter \d+(.\d))/i;let result = str.match(reg);/logs [ ‘see Chapter 3.4.5.1’, ‘Chapter 3.4.5.1’, ‘.1’, index: 22, input: ‘For more information, see Chapter 3.4.5.1’ ]/‘see Chapter 3.4.5.1’ 是整个匹配。 ‘Chapter 3.4.5.1’ 被’(chapter \d+(.\d))‘捕获。 ‘.1’ 是被’(.\d)‘捕获的最后一个值。 ‘index’ 属性(22) 是整个匹配从零开始的索引。 ‘input’ 属性是被解析的原始字符串。2.2.3 replace将字符串中指定字符替换成其他字符,或替换成一个与正则表达式匹配的字符串。 str.replace(sub/reg,val):str: 源字符串sub: 使用字符串来检索被替换的文本reg: 使用RegExp对象来检索来检索被替换的文本val: 指定替换文本返回替换成功之后的字符串,不改变源字符串内容。let str = “hello leo!";let res = str.replace(’leo’,‘pingan’);//“hello pingan!“val可以使用特殊变量名:变量名代表的值$$插入一个 “$"。$&插入匹配的子串。$插入当前匹配的子串左边的内容。$‘插入当前匹配的子串右边的内容。$n假如第一个参数是 RegExp对象,并且 n 是个小于100的非负整数,那么插入第 n 个括号匹配的字符串。提示:索引是从1开始let str = “hello leo!";let res = str.replace(/(\w+)\s* \s*(\w+)/, “$2:$1”);// “leo:hello!“2.2.4 split将一个字符串,按照指定符号分割成一个字符串数组。 str.split(sub[, maxlength]):str: 源字符串sub: 指定的分割符号或正则maxlength: 源字符串let str = “hello leo!";let res = str.split(); //[“hello leo!"]let res = str.split(””); //[“h”, “e”, “l”, “l”, “o”, " “, “l”, “e”, “o”, “!"]let res = str.split(” “);//[“hello”, “leo!"]let res = str.split(/\s+/);//[“hello”, “leo!"]let res = str.split(”",3);//[“h”, “e”, “l”]2.3 使用情况当我们想要查找一个字符串中的一个匹配是否找到,可以用test或search方法。当我们想要得到匹配的更多信息,我们就需要用到exec或match方法。3.正则表达式符号介绍详细的每个符号的用法,可以查阅 W3school JavaScript RegExp 对象3.1 修饰符修饰符描述i执行对大小写不敏感的匹配。g执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。m执行多行匹配。let str = “hello leo!“let res = /Leo/i.test(str); // i 不区分大小写 所以返回truelet res = /Leo/.test(str); // fasle3.2 方括号用于查找指定返回之内的字符:表达式描述[abc]查找方括号之间的任何字符。[^abc]查找任何不在方括号之间的字符。[0-9]查找任何从 0 至 9 的数字。[a-z]查找任何从小写 a 到小写 z 的字符。[A-Z]查找任何从大写 A 到大写 Z 的字符。[A-z]查找任何从大写 A 到小写 z 的字符。[adgk]查找给定集合内的任何字符。[^adgk]查找给定集合外的任何字符。(red)查找任何指定的选项。let str = “hello leo!";let res = str.match(/[a-m]/g);//[“h”, “e”, “l”, “l”, “l”, “e”]let res = str.match(/[^a-m]/g);//[“o”, " “, “o”, “!"]3.3 元字符元字符是拥有特殊含义的字符:元字符描述.查找单个字符,除了换行和行结束符。\w查找单词字符。\W查找非单词字符。\d查找数字。\D查找非数字字符。\s查找空白字符。\S查找非空白字符。\b匹配单词边界。\B匹配非单词边界。\0查找 NUL 字符。\n查找换行符。\f查找换页符。\r查找回车符。\t查找制表符。\v查找垂直制表符。\xxx查找以八进制数 xxx 规定的字符。\xdd查找以十六进制数 dd 规定的字符。\uxxxx查找以十六进制数 xxxx 规定的 Unicode 字符。let str = “hello leo hi pingan!";let res = str.match(/o\s/g);//[“o “, “o “]let res = str.match(/\s/g);//[” “, " “, " “]3.4 量词量词描述n+匹配任何包含至少一个 n 的字符串。n*匹配任何包含零个或多个 n 的字符串。n?匹配任何包含零个或一个 n 的字符串。n{X}匹配包含 X 个 n 的序列的字符串。n{X,Y}匹配包含 X 至 Y 个 n 的序列的字符串。n{X,}匹配包含至少 X 个 n 的序列的字符串。n$匹配任何结尾为 n 的字符串。^n匹配任何开头为 n 的字符串。?=n匹配任何其后紧接指定字符串 n 的字符串。?!n匹配任何其后没有紧接指定字符串 n 的字符串。let str = “hello leo!";let res = str.match(/^hello/g);// [“hello”]let res = str.match(/^pingan/g);//null4. 正则表达式拓展(ES6)4.1 介绍在ES5中有两种情况。参数是字符串,则第二个参数为正则表达式的修饰符。let a = new RegExp(‘abc’, ‘i’);// 等价于let a = /abx/i;参数是正则表达式,返回一个原表达式的拷贝,且不能有第二个参数,否则报错。let a = new RegExp(/abc/i);//等价于let a = /abx/i;let a = new RegExp(/abc/, ‘i’);// Uncaught TypeErrorES6中使用: 第一个参数是正则对象,第二个是指定修饰符,如果第一个参数已经有修饰符,则会被第二个参数覆盖。new RegExp(/abc/ig, ‘i’);4.2 字符串的正则方法常用的四种方法:match()、replace()、search()和split()。4.3 u修饰符添加u修饰符,是为了处理大于uFFFF的Unicode字符,即正确处理四个字节的UTF-16编码。/^\uD83D/u.test(’\uD83D\uDC2A’); // false/^\uD83D/.test(’\uD83D\uDC2A’); // true由于ES5之前不支持四个字节UTF-16编码,会识别为两个字符,导致第二行输出true,加入u修饰符后ES6就会识别为一个字符,所以输出false。 注意: 加上u修饰符后,会改变下面正则表达式的行为:(1)点字符点字符(.)在正则中表示除了换行符以外的任意单个字符。对于码点大于0xFFFF的Unicode字符,点字符不能识别,必须加上u修饰符。var a = “????”;/^.$/.test(a); // false/^.$/u.test(a); // true(2)Unicode字符表示法使用ES6新增的大括号表示Unicode字符时,必须在表达式添加u修饰符,才能识别大括号。/\u{61}/.test(‘a’); // false/\u{61}/u.test(‘a’); // true/\u{20BB7}/u.test(’????’); // true(3)量词使用u修饰符后,所有量词都会正确识别码点大于0xFFFF的 Unicode 字符。/a{2}/.test(‘aa’); // true/a{2}/u.test(‘aa’); // true/????{2}/.test(’????????’); // false/????{2}/u.test(’????????’); // true(4)i修饰符不加u修饰符,就无法识别非规范的K字符。/[a-z]/i.test(’\u212A’) // false/[a-z]/iu.test(’\u212A’) // true检查是否设置u修饰符:使用unicode属性。const a = /hello/;const b = /hello/u;a.unicode // falseb.unicode // true4.4 y修饰符y修饰符与g修饰符类似,也是全局匹配,后一次匹配都是从上一次匹配成功的下一个位置开始。区别在于,g修饰符只要剩余位置中存在匹配即可,而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”] 剩余 ‘_aa_a’r2.exec(s) // nulllastIndex属性:指定匹配的开始位置:const a = /a/y;a.lastIndex = 2; // 从2号位置开始匹配a.exec(‘wahaha’); // nulla.lastIndex = 3; // 从3号位置开始匹配let c = a.exec(‘wahaha’);c.index; // 3a.lastIndex; // 4返回多个匹配: 一个y修饰符对match方法只能返回第一个匹配,与g修饰符搭配能返回所有匹配。‘a1a2a3’.match(/a\d/y); // [“a1”]‘a1a2a3’.match(/a\d/gy); // [“a1”, “a2”, “a3”]检查是否使用y修饰符: 使用sticky属性检查。const a = /hello\d/y;a.sticky; // true4.5 flags属性flags属性返回所有正则表达式的修饰符。/abc/ig.flags; // ‘gi'5. 正则表达式拓展(ES9)在正则表达式中,点(.)可以表示任意单个字符,除了两个:用u修饰符解决四个字节的UTF-16字符,另一个是行终止符。 终止符即表示一行的结束,如下四个字符属于“行终止符”:U+000A 换行符(n)U+000D 回车符(r)U+2028 行分隔符(line separator)U+2029 段分隔符(paragraph separator)/foo.bar/.test(‘foo\nbar’)// false上面代码中,因为.不匹配\n,所以正则表达式返回false。 换个醒,可以匹配任意单个字符:/foo[^]bar/.test(‘foo\nbar’)// trueES9引入s修饰符,使得.可以匹配任意单个字符:/foo.bar/s.test(‘foo\nbar’) // true这被称为dotAll模式,即点(dot)代表一切字符。所以,正则表达式还引入了一个dotAll属性,返回一个布尔值,表示该正则表达式是否处在dotAll模式。const re = /foo.bar/s;// 另一种写法// const re = new RegExp(‘foo.bar’, ’s’);re.test(‘foo\nbar’) // truere.dotAll // truere.flags // ’s’/s修饰符和多行修饰符/m不冲突,两者一起使用的情况下,.匹配所有字符,而^和$匹配每一行的行首和行尾。参考资料1.MDN 正则表达式 2.W3school JavaScript RegExp 对象本部分内容到这结束Author王平安E-mailpingan8787@qq.com博 客www.pingan8787.com微 信pingan8787每日文章推荐https://github.com/pingan8787…ES小册es.pingan8787.com