小生愛

实例1 : exec lastChild

实例2 : 限定符{n,m}

实例3 : 非贪婪匹配?

实例4 : 边界符 ^ $

实例5 : . 字符匹配符

实例6 : | 选择匹配符

实例7 : ()子表达式 子匹配 断言

实例8 : [] [^]

实例9 : \b \B 边界符

实例10 : \d \D 数字字符

实例11 : \s \S 空白字符 非空白字符

实例12 : 匹配元字符

实例13 : 修饰符

实例14 : replace

实例15 : search

实例16 : split

实例17 : RegExp.$1 - RegExp.$99

正则表达式 实例练习:

实例1. 字符去重 保留一个

实例2. 去除重复字符

实例3. 查找重复的CSS样式

实例4. \b边界符与[\b]退格符

实例5. 正则\0空字符与字符串\0空字符 ( 一般做split分隔符比较好 )

实例6. 匹配数字后面的字母( ?!的应用 )

实例7. 一些细节实例

实例8. 正则表达式匹配原理

// exec lastIndex _______________________________________________________________________ // 没设置g的exec实例 var reg = /abc/; var str = 'gbabcabcabc'; console.log(reg.exec(str)); // 没有设置全局属性 每次都从第0个位置查找 console.log(reg.lastIndex); console.log(reg.exec(str)); // lastIndex属性对match没有影响 console.log(str.match(reg)); console.log(reg.lastIndex); console.log(str.match(reg)); // 设置了g的exec实例 var reg = new RegExp('abc', 'g'); var str = 'gbabcabcabc'; console.log(reg.exec(str)); // 设置了全局属性 lastIndex值将在上一次查找的位置index处 + 匹配的字符长度 // 下次搜索将从新的lastIndex位置开始搜索 console.log(reg.lastIndex); console.log(reg.exec(str)); // {n,m} 限定符 _______________________________________________________________________ // {1} : 匹配一个字符 var reg = /c{1}/; // {1, 3} : 匹配1~3个字符 匹配时默认选择贪婪匹配 var reg2 = /c{1,3}/; // {1, } : 匹配最少一个字符 var reg3 = /c{1,}/; var str = 'cainiao'; var str2 = 'cccniao'; var str3 = 'ccccccniao'; // 输出c console.log(reg.exec(str)); // 输出ccc console.log(reg2.exec(str2)); // 输出cccccc console.log(reg3.exec(str3)); // {n,m}? 非贪婪匹配 _______________________________________________________________________ // {1,4}? : 非贪婪匹配后 只匹配1个字符 var reg = /c{1,4}?/; var str = 'ccccainiao'; // 输出c console.log(reg.exec(str)); // ^ $ 边界符 _______________________________________________________________________ // ^ : 匹配以c字符开头 var reg = /^c{1,2}?/; // $ : 匹配以c字符结尾 var reg2 = /c+?$/; var str = 'cccc小生爱'; var str2 = '小生爱cccc'; // 输出c console.log(reg.exec(str)); // 输出null console.log(reg.exec(str2)); // 输出null console.log(reg2.exec(str)); // 输出cccc // 第一次c+匹配 c 不满足$结尾规则 继续匹配 // 第二次匹配 cc 依旧不满足规则 继续匹配 // 第三次匹配 ccc 不满足 继续 // 第四次匹配 cccc 满足要求 返回该值 console.log(reg2.exec(str2)); // . 字符匹配符 _______________________________________________________________________ // . 匹配除了\n外的所有字符 var reg = /.{1,3}/; var str = '魔兽世界'; var reg2 = /^a/; var str2 = '\nabc'; // 输出魔兽世 console.log(reg.exec(str)); // 输出null 因为.不匹配\n console.log(reg2.exec(str2)); // | 选择匹配符 _______________________________________________________________________ // | : 选择匹配符 匹配左边或右边的字符 var reg = /c+|b+?/; var str = 'aaabbb'; // 输出b console.log(reg.exec(str)); // () ?= ?! ?: _______________________________________________________________________ // (a|b) : 子表达式 // \1 : 子匹配 var reg = /^(a|b)\1/; var str = 'aabb'; // 输出aa // 子匹配的值是 a console.log(reg.exec(str)); // (a|b) : 子表达式 // \1 : 子匹配 // ?: : 不记录子表达式匹配到的结果 var reg = /^(?:a|b)\1/; var str = 'aabb'; // 子匹配没有记录 没有值 输出null console.log(reg.exec(str)); // 正向断言 var reg = /a(?=b*)a+/; var reg2 = /a(?=b+)/; var str = 'abba'; /* ?= : 正向断言 1. 先匹配第一个a 2. 匹配1~N个b 这里按最大2匹配 匹配到了 3. 继续匹配 1个a (匹配到的b并不在匹配结果里 这时再匹配a 所以匹配不到) 4. 输出null */ console.log(reg.exec(str)); /* ?= : 正向断言 1. 先匹配第一个a 2. 匹配1~N个c 这里按最大2个b 匹配到了 3. 继续匹配 a 3. 输出a */ console.log(reg2.exec(str)); // 反向断言 var reg = /a(?!c+)a+?/; var reg2 = /a(?!c)?/; var str = 'abba'; /* ?! : 反向断言 1. 先匹配第一个a 2. 匹配后面是否不存在2个c 匹配到了 继续匹配a+? 3. 未匹配到 4. 输出null */ console.log(reg.exec(str)); /* ?! : 反向断言 1. 先匹配第一个a 2. 匹配1个c 未匹配到 3. 输出a */ console.log(reg2.exec(str)); // 补充断言实例 var str = 'win98'; var reg = /(?=win)98/; var reg2 = /(?!aa)98/; /* 1. 匹配\b边界符后面是否跟这个win 匹配成功 (?=xx) 必须是某某后面跟着这个 2. 匹配\b后面是否跟着98 未匹配到 输出null */ console.log(reg.exec(str)); /* 1. 匹配某某字符后面是否不是aa 2. 先从\b开始 匹配成功 然后匹配98 未匹配到 3. 从w开始 匹配陈公告 然后匹配98 未匹配到 4. 从i开始 。。。 从n开始 匹配成功 然后匹配98 匹配成功 5. 输出98 */ console.log(reg2.exec(str)); var str = '&cc&&cc##cc#cc'; var reg = /(?:cc(?=##))|(?:cc(?=#))/; console.log(str.match(reg)); // [] [^] _______________________________________________________________________ // [abc] : 匹配abc中的任何一个字符 var reg = /^[abc]+/; var str = 'aabcadeg'; // [^abc] : 不包含abc中的任意一个字符 var reg2= /[^abc]+?/; var str2 = 'abcdef'; // 输出 abca console.log(reg.exec(str)); // 输出d console.log(reg2.exec(str2)); // * + 区别 _______________________________________________________________________ var str = 'zzooz'; var reg = /o*/; // 从最左侧字母z开始匹配 未匹配到 输出null console.log(reg.exec(str)); // 从最左侧第一个字母z开始匹配 未匹配到 输出null console.log(str.match(reg)); var str2 = 'ozooz'; var reg2 = /o*/g; // 从最左侧第一个字母0开始匹配 匹配到 输出 o console.log(reg2.exec(str2)); // 继续从字母z 开始匹配 未匹配到 输出null console.log(reg2.exec(str2)); // lastIndex 位置未改变 重新从z开始匹配 未匹配到 输出null console.log(reg2.exec(str2)); /* 1. 从字母0开始匹配 匹配到 输出第一个匹配o 2. 从第2个位置 z继续匹配 未匹配到 输出第2个匹配null 3. 从第3个位置 o继续匹配 匹配到 输出最大匹配值 oo 4. 从第5个位置 z继续匹配 未匹配到 输出null 5. 从下一个位置 继续匹配 因为没字符 未匹配到 输出null */ console.log(str2.match(reg2)); console.log('-------------------'); var str3 = 'zoozooo'; var reg3 = /o+/g; // 1. 从第一个字母开始查找匹配的字母o 匹配到输出oo // 2. 一直搜索到第2个字母o 输出ooo console.log(reg3.exec(str3)); console.log(reg3.exec(str3)); console.log(str3.match(reg3)); // \b 边界符 _______________________________________________________________________ var str = 'caca'; var reg = /\bc/; console.log(reg.exec(str)); var str2 = 'c caa'; var reg2 = /c\bc/; /* 1. c\b 匹配c& 匹配到 但是匹配结果不包含\b匹配的值 所以这部匹配的结果是c 2. 继续匹配第2个c 没有cc的结果 未匹配到 3. 输出null */ console.log(reg2.exec(str2)); var str3 = 'caca'; var reg3 = /\Bc/; // \B 匹配[a-zA-Z0-9_]中任意一个字符 符合条件的是第2个c 输出c console.log(reg3.exec(str3)); // \d \D 数字字符 _______________________________________________________________________ var str = 'abc7'; // \d 匹配数字字符 var reg = /\d/; // \D 匹配非数字字符 var reg2 = /\D/; console.log(reg.exec(str)); console.log(reg2.exec(str)); // \s \S _______________________________________________________________________ var reg = /\s{2}.+/; var str='ss \nis a test \nString.'; // \s{2} 匹配了 空格和\n // . 不能匹配\n // 输出' \nis a test '; console.log(reg.exec(str)); var reg2 = /\Sabc/; var str2 = '\n aabc def'; // \S 匹配了第一个a // 输出aabc console.log(reg2.exec(str2)); // 匹配空格另一种方式 var reg3 = / +/; var str3 = ' abc'; console.log(reg3.exec(str3)); // 匹配所有字符 var reg4 = /[\s\S]+/; var str4 = ' abc'; console.log(reg4.exec(str4)); // 元字符 _______________________________________________________________________ var str = 'a{1}****b'; // \* 匹配 *这个字符 // \{ \} 匹配括号字符 var reg = /\w\{1\}\*+?\w/; // \*+? 按最小匹配 因为后面还要匹配一个字符 所以这里匹配**** // 输出a{1}****b console.log(reg.exec(str)); // 字符串中要有\必须要写2个 转意一个 var str2 = 'a\\b'; // 匹配\元字符 要写成\\ 进行转意 var reg2 = /\\b/; // 输出\b console.log(reg2.exec(str2)); // i m g _______________________________________________________________________ var str = 'AAAA'; // i 不区分大小写 var reg = /a/i; // 输出A console.log(reg.exec(str)); var str2 = 'abc\nefg'; // m 匹配每行 // g 匹配全局 var reg2 = /^\w/mg; // 匹配是否带空白符 var reg3 = /c(?=\s)/; // 输出[a, e] console.log(str2.match(reg2)); // 输出c console.log(reg3.exec(str2)); // replace _______________________________________________________________________ var str = 'acab\naca'; /* 1. 匹配以a开头 并且后买年跟着c的字符 匹配到开头的ac 2. 继续匹配到第2对ac字符时 因为不是以a开头所以未匹配到 3. 输出ecab\naca */ var reg = /^a(?=c)/g; console.log(str.replace(reg, 'e')); /* 1. 匹配以a开头 并且后买年跟着c的字符 匹配到开头的ac 2. 继续匹配到第2对ac字符时 符合匹配规则 3. 输出ecab\neca */ var reg2 = /^a(?=c)/mg; console.log(str.replace(reg2, 'e')); /* 1. 匹配正则 匹配到a c 2. $2 获取第2个子匹配 3. $1 获取第1个子匹配 4. 调换 $1 $2的位置 5. 输出dc ae */ var reg3 = /(\w)\s(\w)/; var str3 = 'da ce'; console.log(str3.replace(reg3, '$2 $1')); var reg4 = /(b)(c)d/; var str4 = 'abcde'; // 如果想使用$字符替换 需要写2个$$ console.log(str4.replace(reg4, '$$1')); var reg5 = /c/g; var str5 = 'acecf'; /* 1. 匹配子串左侧的文本 2. 首先匹配到第一个c 然后获取该匹配字符左侧文本a 替换第一个a 当前字符串变成 aaecf 3. 继续匹配第二个c 然后获取该匹配字符左侧的文本ace(注意这里获取原文本) 4. 从第2个匹配字符c处开始替换 当前字符变成aaeacef */ console.log(str5.replace(reg5, '$`')); /* 1. 匹配子串右侧的文本 2. 首先匹配第一个c 然后获取该匹配字符串右侧文本ecf 替换第一个c 当前字符变成 aecfecf 3. 继续匹配第2个c 然后获取该匹配字符串右侧文本f 4. 从第2个匹配字符c处开始替换 当前字符变成aecfeff */ console.log(str5.replace(reg5, "$'")); // replace _______________________________________________________________________ /* 1. search 搜索匹配字符第一次出现的位置 设置不设置gm对此没有影响 2. 查找匹配第一个e的位置 输出5 3. 这里的g m对search没有影响 */ var str = 'abcd\nefabcdef'; var reg = /e/gm; console.log(str.search(reg)); // 使用exec的index属性效果相同 console.log(reg.exec(str).index); // split _______________________________________________________________________ var str = 'accdeef'; var reg = /(\w)\1/; /* 1. 匹配2个相同连续字符 先匹配cc => [a,c,deef] 2. 再匹配ee => [a,c,d,e,f] split会把子表达式的匹配值也显示到匹配结果里 */ console.log(str.split(reg)); var str2 = 'accdeef'; var reg2 = /c/; /* 1. 根据字母c 进行字符分割匹配正则 => [a, cdeef] 2 .继续匹配正则 [a, '', deef] 3. 参数2 表示只获得2个匹配值 */ console.log(str2.split(reg2, 2)); var str3 = 'acc\ndeef'; var reg3 = /(\w)\1/gm; /* 1. 根据2个连续相同字符进行字符分割 => [a, \ndeef] 2. 继续匹配 [a,\nd,f] 3. g m是否添加对split无影响 */ console.log(str3.split(reg3)); // search _______________________________________________________________________ var str = 'a\nccdeef'; var reg = /c/gm; // 检索是否有匹配的正则 如果存在返回第一次匹配位置 // 如果不存在返回 -1 // 是否设置gm没有影响 console.log(str.search(reg)); // RegExp.$1 - RegExp.$99 _______________________________________________________________________ // 第一次正则匹配 var str = 'abcdef'; var reg = /(a)(b)/; str.match(reg); // 第2次正则匹配 var str2 = 'fe'; var reg2 = /(f)/; str2.match(reg2); // 2次正则匹配 只记录最后一次匹配的值 // 所以如果要获取值 要在下一次匹配前获取 console.log(RegExp.$1,RegExp.$2); // 字符去重 保留一个_______________________________________________________________________ var str = 'abcacdaefe'; var reg = /(\w)(?=.*\1)/g; /* 1. 字符去重 2. replace首先根据 正则匹配所有子表达式 3. 然后把匹配的子表达式结果替换成'' 4. 输出bcdafe */ console.log(str.replace(reg, '')); // 去除重复字符 _______________________________________________________________________ var str = 'abcacdaefe'; var reg = /(\w)\1+/g; /* 1. 先进行字母排序 变成aaabccdeef 2. 然后进行字符替换 3. 输出bdf */ console.log(str.split('').sort().join('').replace(reg, '')); // 匹配出现过一次已上的CSS样式 _______________________________________________________________________ var str1 = '11'; var str2 = '22'; var reg = /([\w-]+\s*:\s*[#\d\s\w]*)(?=.*\1)/g; // 输出["color:#000", "font-size:12px"] console.log((str1+str2).match(reg)); /* * \b 与 [\b]的区别 * \b 表示边界符 [^a-zA-Z0-9_] * [\b] 表示转义字符\b===回退符 只能匹配字符串中的转义字符\b */ var reg = /\ba/; var reg2 = /a[\b]a/; var str = ' a\ba'; // 匹配边界符+a 输出a console.log(reg.exec(str)); // 匹配a+退格符\b+a 输出a\ba 页面中不可见\b 输出长度是3 console.log(reg2.exec(str)); /* * 正则\0 与 字符串\0 */ // \0 表示空字符 null var reg = /\0a/; // 字符串里\0 也表示空字符 null var str = ' a\0a'; // 匹配第2个a 输出"空字符+a" console.log(reg.exec(str)[0].length); /* * 匹配数字后面的字母 */ var str = '1aa2bc3@'; // ?! 首先匹配位置 匹配到1, 2, 3 // 然后匹配字母 匹配到[aa bc] var reg = /(?![\d])[a-z]+/g; console.log(str.match(reg)); // 匹配 c后面不包含结尾符 输出null var str = 'abc'; var reg = /c(?!$)/; console.log(reg.exec(str)); // 匹配某个字符后面不包含字母+结尾符 // 从第一个位置^开始匹配符合 输出^字符 "" var str = 'abcdefd'; var reg = /(?![a-zA-Z]+$)/; console.log(reg.exec(str)); // 匹配从^到结尾不全是字母 没匹配到输出null var str = 'abcd3efg'; var reg = /^(?![a-zA-Z]+$)/; console.log(reg.exec(str)); // ^(?!a$)(?!b$) : 按顺序分别匹配(?!a$)与(?!b$) 不是同时匹配 // (?!ab$) : 同时匹配 var str = 'ab'; var reg = /^(?!a$)(?!b$)/; // var reg = /^(?!ab$)/; console.log(reg.exec(str)); /* * 匹配包含字母 数字 特殊字符的字符串 */ // ^ : 匹配起始位置 // (?![a-zA-Z]+$) : 匹配不全是字母 // (?!\d+$) : 匹配不全是数字 // (?![!@#$%^&*]+$) : 匹配不包含特殊字符 // (?![a-zA-z\d]+$) : 匹配不包含字母数字混合 // (?![a-zA-z!@#$%^&*]+$) : 匹配不包含字母和特殊字符 // (?![\d!@#$%^&*]+$) : 匹配不包含数字和特殊字符 // [a-zA-Z\d!@#$%^&*]+$ : 匹配字母数字特殊字符 var str = 'abcd3@efg'; var reg = /^(?![a-zA-Z]+$)(?!\d+$)(?![!@#$%^&*]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&*]+$)(?![\d!@#$%^&*]+$)[a-zA-Z\d!@#$%^&*]+$/ // 输出abcd3@efg console.log(reg.exec(str)); /* 匹配()内容,()里面可能有@—*^&'#干扰字符或[]{}内容 不匹配(上)(中) (下)但匹配其他单个字内容,同时匹配(上午)(中将)(下面)等或更多内容 */ var str = '(上a)'; // \( : 匹配左括号 // (?![上中下]\)) : 不包含上中下和右括号 // .+ : 匹配其他字符 // \) : 匹配右括号 var reg = /\((?![上中下]\)).+\)/; console.log(reg.exec(str)); // 匹配q后面跟着一个字符 // 正则在匹配的时候会去掉换行符 所以q后面没有字符 // 输出null var str = 'aq'; var reg = /q[^u]/; console.log(reg.exec(str)); // 这里的 - 表示范围 所以输出null var reg = /[.-@]/; var str ='-'; console.log(reg.exec(str)); // 从右到左 每隔3个数字添加一个分隔符 var str = 'abcd1234586'; // 匹配某个位置到数字结束位置包含3的倍数个数字 // (?!\d) : 表示到数字结束位置 var reg = /(?=(?:\d{3})+(?!\d))/g; /* * 排除环视实现排除型字符组的功能 * 匹配标签 并且标签内不包含该标签 * *号必须作用 ?!整体 这样每次匹配才会都查找?! */ var str = 'abc123 小花'; var reg = /((?!<\/?b>).)*<\/b>/; /* * NFA 表达式主导 * 首先字母b匹配字母a 并保存备用序列 未匹配到a 字符 正则 ,bca a?, * 回溯 匹配忽略a后的字符空 匹配到 * 传送带继续移动到下一个位置b,ca 重新开始匹配 * c匹配字母a 并保存备用序列 未匹配到a 字符 正则 b,ca a?, * 回溯 匹配忽略a后的字符空 匹配到 * ... 以此类推 输出['', '', a, ''] */ var reg = /a?/g; var str = 'bca'; // 匹配原理 _______________________________________________________________________ /* * 匹配的过程 * 首先匹配第一个字符a 匹配到 * 匹配b?的时候 根绝匹配优先原则先匹配b 并记录备用序列 另外一个未尝试的正则分支和该该分支在字符串中的位置 匹配到b 字符 正则 a,bc ab?,c * 继续匹配c 匹配到 退出 (这里没有执行回溯 因为第一次匹配到了) */ var reg = /ab?c/; var str = 'abc'; /* * 匹配正则表达式中的字母a 匹配到 * 根据优先匹配原则 匹配字母b 并记录备用序列(另外一个 未尝试的正则分支和该分支在字符串中的位置) 未匹配到b * 字符 正则 a,c ab?,c * 回溯到最近的备用序列中的一个位置 匹配c 匹配到 */ var reg = /ab?c/; var str = 'ac'; /* * 匹配正则表达式中的字母a 匹配到 * 根据优先匹配原则匹配字母b 并记录备用序列(另外一个未尝试 的正则分支和该分支在字符串中的位置) 匹配到字母b 字符 正则 a,bX ab?,c * 匹配字母c 未匹配到 进行回溯到最近的一个备用序列位置 * 字母b匹配字母c 未匹配到 * 进入到字符串中的下一个位置b前面的位置 重新开始匹配正则中的的字母a 匹配失败 * 再进入到字符串的下一个位置X前面的位置 重新开始匹配正则中字母a 匹配失败 * 最终宣告失败 */ var reg = /ab?c/; var str = 'abX'; // * + 匹配过程 /* * 对于+号 首先正则把\d+解析成 /\d\d?.../ * 从字符的第一个位置匹配第一个\d 失败 直到数字1时 匹配到 * 继续匹配第2个\d? 根据优先匹配原则先匹配\d 并记录备用序列(另外一个未尝试 的正则分支和该分支在字符串中的位置) 匹配到数值2 字符 正则 a 1,234 num \d\d?,... * 继续匹配第3个\d? 根据优先匹配原则先匹配\d 并记录备用序列(另外一个未尝试 的正则分支和该分支在字符串中的位置)匹配到数字3 字符 正则 a 12,34 num \d\d?,\d?,... * 继续相同的步骤匹配第4个\d? * 匹配第5个\d? 根据优先匹配原则先匹配\d 并记录备用序列(另外一个未尝试 的正则分支和该分支在字符串中的位置) 未匹配到 字符 正则 a 1234, num \d\d?,\d?,\d?,\d?,... * 回溯到第5个\d保存的备用序列值用正则后面的空白符匹配到数字4后面的空白 结束匹配 返回1234 */ var reg = /\d+/; var str = 'a 1234 num'; /* * 首先把.*解析成 .{0}.?[0-9][0-9] * 匹配.{0}匹配到左侧空 * 匹配第1个.? 记录备用序列(一) 字符 正则 ,c95u .{0}.?,[0-9][0-9] * 匹配第2个.? 记录备用序列(二) 字符 正则 c,95u .{0}.?,.?,[0-9][0-9] * 匹配第3个.? 记录备用序列(三) 字符 正则 c9,5u .{0}.?,.?,.?,[0-9][0-9] * 匹配第4个.? 记录备用序列(四) 字符 正则 c95,u .{0}.?,.?,.?,.?,[0-9][0-9] * 继续匹配[0-9] 未匹配到 回溯到备用序列四 u匹配[0-9]未匹配到 * 回溯到备用序列三 5匹配到数字[0-9] 但u未匹配到第2个[0-9] * 回溯到备用序列二 9匹配到[0-9] 5匹配到[0-9] 匹配成功 */ var reg = /.*[0-9][0-9]/; var str = 'c95u'; /* * 多选匹配原理 * 从字符串的第一个位置开始匹配ab 并记录备用序列 匹配到a 字符 正则 ,adac ab,ac * 继续匹配字母b 未匹配 进行回溯 字母a匹配a 匹配成功 继续匹配c 未匹配 从第2个字符重新开始 字符 正则 a,dac ab,ac * 字符d未匹配a 回溯字符d未匹配第2个多选中的a 再从第3个字符开始... */ var reg = /ab|ac/; var str = 'adac';