有部分和 DOM 相关的例题,可以等后续学习了相关知识点后再刷。
匹配座机号
规则:
- 开始是 1 到 3 个数字
 - 接着是一个减号 
- - 最后是 4 到 8 个数字
 
var reg = /^\d{1,3}-\d{4,8}$/;console.log(reg.test('021-12345678')); // trueconsole.log(reg.test('21-12345678')); // trueconsole.log(reg.test('021-1234')); // trueconsole.log(reg.test('1-12345678')); // trueconsole.log(reg.test('021-1234567890')); // false,因为最后的数字部分超过8个console.log(reg.test('021-123')); // false,因为最后的数字部分少于4个console.log(reg.test('02112345678')); // false,因为没有减号console.log(reg.test('01234-12345678')); // false,因为开始部分的数字超过3个
匹配手机号
规则:
- 手机号码总共 11 位
 - 第一位固定为 1
 - 第二位是 3、4、5、6、7、8 或 9
 
var reg = /^1[3-9]\d{9}$/;console.log(reg.test('13800138000')); // true,这是一个有效的手机号码console.log(reg.test('23800138000')); // false,因为手机号码的第一位必须为1console.log(reg.test('1580013800')); // false,因为手机号码必须是11位console.log(reg.test('15800138000a')); // false,因为手机号码必须全部由数字构成console.log(reg.test('12000138000')); // false,因为手机号码的第二位数字必须在3-9之间
匹配中国人的姓名
规则:两到四个汉字
var reg = /^[\u4e00-\u9fa5]{2,4}$/;console.log(reg.test('张三')); // trueconsole.log(reg.test('李四五六七')); // false, 因为超过4个汉字console.log(reg.test('老王')); // trueconsole.log(reg.test('小明1')); // false, 因为包含数字console.log(reg.test('赵')); // false, 因为少于2个汉字
匹配密码
规则:
- 必须是 6-12 位的字符
 - 只能包含数字、字母、下划线
 
var reg = /^\w{6,12}$/;// 等同于:// var reg = /^[0-9a-zA-Z_]{6,12}$/console.log(reg.test('abcdef')); // trueconsole.log(reg.test('123456')); // trueconsole.log(reg.test('abc123_')); // trueconsole.log(reg.test('abc123__')); // trueconsole.log(reg.test('abc123__!')); // false, 因为包含除数字、字母、下划线之外的字符console.log(reg.test('a1_')); // false, 因为少于6个字符console.log(reg.test('1234567890123456')); // false, 因为超过12个字符
匹配邮箱
规则:
- 电子邮件地址开始必须是一个或多个字母、数字、点、下划线、百分号、加号或减号
 - 接着是一个 @ 符号
 - 接下来是一个或多个字母、数字、点或短划线(域名)
 - 然后是一个点
 - 电子邮件地址结束必须是两个或更多字母(顶级域)
 
var reg = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/;console.log(reg.test('john.doe@example.com')); // trueconsole.log(reg.test('john@example.com')); // trueconsole.log(reg.test('j@example.co.uk')); // trueconsole.log(reg.test('john.doe@exa_mple.com')); // false, 因为域名部分包含了下划线console.log(reg.test('john.doe@.com')); // false, 因为域名部分以点开始console.log(reg.test('john.doe@example')); // false, 因为没有顶级域console.log(reg.test('john.doe@example.c')); // false, 因为顶级域只有一个字符
匹配一个正数
规则:
- 开始是一个或多个数字
 - 接着可能有小数点也可能没有
 - 如果有小数点,则小数点后面必须还有一个或多个数字
 
var regex = /^\d+(\.\d+)?$/;console.log(regex.test('123')); // trueconsole.log(regex.test('0.123')); // trueconsole.log(regex.test('123.0')); // trueconsole.log(regex.test('123.456')); // trueconsole.log(regex.test('.123')); // false, 必须有整数部分console.log(regex.test('123.')); // false, 如果有小数点,小数点后面必须有数字console.log(regex.test('-123')); // false, 不匹配负数console.log(regex.test('abc')); // false, 不匹配非数字字符console.log(regex.test('123abc')); // false, 不匹配数字后面带有非数字字符的情况console.log(regex.test(' ')); // false, 不匹配空格等非数字字符
匹配一个小数
规则:
- 开始是一个负号 
-,也可以没有 - 然后是一个或多个数字
 - 然后是小数点 
. - 然后是一个或多个数字
 
var reg = /^-?\d+\.\d+$/;// var reg = /^-?\d+\.{1}\d+$/;console.log(reg.test('123.456')); // trueconsole.log(reg.test('-123.456')); // trueconsole.log(reg.test('.123')); // false, 必须有整数部分console.log(reg.test('123.')); // false, 如果有小数点,小数点后面必须有数字
匹配一个整数
规则:
- 开始是一个负号 
-,也可以没有 - 然后是一个或多个数字
 - 然后是一个小数点,也可以没有
 - 如果有小数点的话,则后续必须出现一个或多个 0
 
var reg = /^-?\d+(\.0+)?$/;console.log(reg.test('123')); // trueconsole.log(reg.test('-123')); // trueconsole.log(reg.test('-123.00')); // trueconsole.log(reg.test('-123.0')); // trueconsole.log(reg.test('-123.0001')); // false,小数点后只能出现 0console.log(reg.test('123.456')); // false, 有小数部分console.log(reg.test('abc')); // false, 不是数字
匹配连续数字
现在存在一个字符串:"433afdsaf34542fsdssfsd234",要求找出这段字符串中连续 3 个字符都是数字的所有字串,参考输出:["433", "345", "234"]。
var str = "433afdsaf34542fsdssfsd234";var regex = /\d{3}/g;var matches = str.match(regex);if (matches) {console.log("匹配结果: ", matches);} else {console.log("没有匹配项");}// 匹配结果: [ '433', '345', '234' ]
var str = "433afdsaf34542fsdssfsd234";var regex = /\d{3}/g;var matches;var results = [];while ((matches = regex.exec(str)) !== null) {results.push(matches[0]);}if (results.length > 0) {console.log("匹配结果: ", results);} else {console.log("没有匹配项");}// 匹配结果: [ '433', '345', '234' ]
获取所有中文字符,并计算数量
测试字符串:"一个包含中、英、数字 abc123 的字符串。"
var str = "一个包含中、英、数字 abc123 的字符串。";var reg = /[\u4e00-\u9fa5]/g;var matches = str.match(reg);if (matches) {console.log(matches)console.log("中文字符的数量: ", matches.length);} else {console.log("没有中文字符");}// [// '一', '个', '包',// '含', '中', '英',// '数', '字', '的',// '字', '符', '串'// ]// 中文字符的数量: 12
找出连续字符
测试字符串:"aaaaaaaabbbbbbbbbccccccdefgggggggg"
期望输出的结果:a``b``c``g
var s = "aaaaaaaabbbbbbbbbccccccdefgggggggg";var reg = /(\w)\1+/g;// var reg = /(?<char>\w)\1+/g;// var reg = /(?<char>\w)\k<char>+/g;while (result = reg.exec(s)) {console.log(result[1])}// a// b// c// g
var str = "aaaaaaaabbbbbbbbbccccccdefgggggggg";var regex = /(.)\1*/g;var matches = str.match(regex);console.log(matches)// [ 'aaaaaaaa', 'bbbbbbbbb', 'cccccc', 'd', 'e', 'f', 'gggggggg' ]var result = matches.filter(s => s.length > 1).map(s => s[0]).join('');console.log(result)// abcg
var str = "aaaaaaaabbbbbbbbbccccccdefgggggggg";var regex = /(.)\1+/g;var matches = str.match(regex);console.log(matches)// [ 'aaaaaaaa', 'bbbbbbbbb', 'cccccc', 'gggggggg' ]var result = matches.map(s => s[0]).join('');console.log(result)// abcg
过滤敏感词
有一个敏感词数组,需要将字符串中出现的敏感词替换为四个星号
敏感词数组:["小逗逼", "捣蛋鬼"]
示例:
- 输入:
"A:男孩子和女孩子之间有什么区别?B:男孩子长大叫小逗逼,女孩子长大叫捣蛋鬼。" - 输出:
"A:男孩子和女孩子之间有什么区别?B:男孩子长大叫****,女孩子长大叫****。" 
function removeSensitiveWords(senWords, s, rep) {var reg = new RegExp(`(${senWords.join("|")})`, "g")return s.replace(reg, rep)}var result = removeSensitiveWords(["小逗逼", "捣蛋鬼"],"A:男孩子和女孩子之间有什么区别?B:男孩子长大叫小逗逼,女孩子长大叫捣蛋鬼。","****")console.log(result)// A:男孩子和女孩子之间有什么区别?B:男孩子长大叫****,女孩子长大叫捣蛋鬼。
解析日期信息
输入:'2015-05-01, 2019-06-19, 2000-04-28'
输出:
[{"y": 2015,"m": 5,"d": 1},{"y": 2019,"m": 6,"d": 19},{"y": 2000,"m": 4,"d": 28}]
var s = '2015-05-01, 2019-06-19, 2000-04-28';var reg = /(\d{4})-(\d{1,2})-(\d{1,2})/g;var result = []s.replace(reg, (_, g1, g2, g3) => {result.push({y: +g1,m: +g2,d: +g3})})console.log(result)// [// { y: 2015, m: 5, d: 1 },// { y: 2019, m: 6, d: 19 },// { y: 2000, m: 4, d: 28 }// ]
解析 html 标题
题目描述:
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>23.08.01</title></head><body><div class="container"><!-- Emmet 速写:(h2{第$章}+p*5>lorem5)*10 --><h2>第1章</h2><p>Lorem ipsum dolor sit amet.</p><p>Vitae sequi aspernatur a reiciendis.</p><p>Recusandae ullam consequatur aut repellendus.</p><p>Sit id debitis laborum quasi.</p><p>Unde laborum ipsam eaque omnis!</p><h2>第2章</h2><p>Lorem ipsum dolor sit amet.</p><p>Reiciendis quia iste illo inventore!</p><p>Ad enim porro molestiae qui?</p><p>Aperiam magni possimus officia iste.</p><p>Unde dolores repudiandae optio odit.</p><h2>第3章</h2><p>Lorem ipsum dolor sit amet.</p><p>Voluptatem officiis esse cum officia.</p><p>Aut tempora nemo obcaecati vero.</p><p>Ab doloremque earum illo. Repudiandae.</p><p>Nobis ducimus quos quas similique!</p><h2>第4章</h2><p>Lorem ipsum dolor sit amet.</p><p>Saepe recusandae aliquam mollitia placeat.</p><p>Sed ex quod enim ut!</p><p>Ratione molestiae molestias iste temporibus.</p><p>In vel cupiditate quas rerum!</p><h2>第5章</h2><p>Lorem ipsum dolor sit amet.</p><p>Quod minima in quia atque.</p><p>Deserunt tempore rerum aut fuga!</p><p>Ratione nesciunt numquam iste eum!</p><p>Quidem numquam animi officia temporibus?</p><h2>第6章</h2><p>Lorem ipsum dolor sit amet.</p><p>Autem natus necessitatibus quos error.</p><p>Id vero hic at suscipit!</p><p>Culpa libero quibusdam est adipisci?</p><p>Nihil enim atque unde dolorem.</p><h2>第7章</h2><p>Lorem ipsum dolor sit amet.</p><p>Saepe magnam fugiat voluptate illum.</p><p>Dolor explicabo tenetur iste quae.</p><p>Ab natus maxime suscipit eaque.</p><p>Possimus soluta aperiam voluptatem quia.</p><h2>第8章</h2><p>Lorem ipsum dolor sit amet.</p><p>Tenetur mollitia maiores adipisci eveniet!</p><p>Quam adipisci laborum doloribus in.</p><p>Expedita architecto eos id vitae!</p><p>Neque similique in excepturi aperiam.</p><h2>第9章</h2><p>Lorem ipsum dolor sit amet.</p><p>Natus quisquam rerum doloribus ex.</p><p>Veritatis minus suscipit nihil repudiandae.</p><p>Soluta exercitationem aspernatur doloribus impedit?</p><p>Tempore eveniet perferendis quasi quae.</p><h2>第10章</h2><p>Lorem ipsum dolor sit amet.</p><p>Voluptate aperiam est dolorem maxime.</p><p>Porro aut dolorem magnam consectetur?</p><p>Dolor quas impedit dolorum molestias!</p><p>Incidunt sapiente expedita blanditiis nesciunt.</p></div><script>// 请在这里编码,使用正则,解析出 div.container 中的所有 h2 元素,按照如下格式返回:// [// "<h2>第1章</h2>", "<h2>第2章</h2>", "<h2>第3章</h2>",// "<h2>第4章</h2>", "<h2>第5章</h2>", "<h2>第6章</h2>",// "<h2>第7章</h2>", "<h2>第8章</h2>", "<h2>第9章</h2>",// "<h2>第10章</h2>"// ]</script></body></html>
参考代码:
<script>// 1. 获取 div.container 的 HTML 内容var containerHTML = document.querySelector(".container").innerHTML;// 2. 编写正则表达式来匹配所有的 h2 元素var reg = /<h2>.*?<\/h2>/g;// 3. 使用 match 方法来获取所有的匹配项var h2Matches = containerHTML.match(reg);console.log(h2Matches);</script>

补充:
就此 demo 而言,因其 HTML 结构比较单一,并没有多么复杂,所以直接通过正则的方式来匹配字符串是没问题的。
但一般来说,使用正则表达式解析 HTML 是一个很糟糕的主意,因为 HTML 的复杂性使得很难编写一个既正确又完整的正则表达式来匹配所有可能的 HTML 变体。一个更好的做法通常是使用一个完整的 HTML 解析器,或者使用浏览器提供的 DOM API。
通过这个 demo,我们需要有这样一个意识:HTML 字符串,在必要的时候也是可以尝试将其转为字符串,然后通过 JS 的正则来处理的。
预查练习:封装判断密码强度的方法
规则:
- 密码长度必须是 6-12 位,如果长度不满足要求,则返回 false
 - 强度判断规则:
- 出现小写字母、大写字母  -> 
弱 - 出现小写字母、大写字母、数字  -> 
中 - 出现小写字母、大写字母、数字、特殊字符(!@#_,.)  -> 
强 
 - 出现小写字母、大写字母  -> 
 - 若所有字符都是非法字符,则返回 false
 
/*** 判断密码强度* @param {String} pwd 密码* @returns "强" | "中" | "弱" | false*/function judgePwd(pwd) {var len = pwd.length;var reg_valid = /^[a-zA-Z\d!@#_,.]+$/; // 只允许大小写字母、数字、特殊字符if (len < 6 || len > 12 || !reg_valid.test(pwd)) return false; // 不满足要求var reg_part1 = "(?=.*[a-zA-Z])"; // 预查大小写字母var reg_part2 = "(?=.*\\d)"; // 预查数字var reg_part3 = "(?=.*[!@#_,.])"; // 预查特殊字符if (new RegExp(`${reg_part1}${reg_part2}${reg_part3}`).test(pwd)) return "强"else if (new RegExp(`${reg_part1}${reg_part2}`).test(pwd)) return "中"else if (new RegExp(`${reg_part1}`).test(pwd)) return "弱"else return false}console.log(judgePwd('123')); // => falseconsole.log(judgePwd('asdfgh')); // => 弱console.log(judgePwd('asd123')); // => 中console.log(judgePwd('asd123!!!')); // => 强console.log(judgePwd('asd123!!!asd123!!!')); // => falseconsole.log(judgePwd('♉♉♉♋♋♋')) // => falseconsole.log(judgePwd('abcABC1!汉字')); // => false
面试题:金额格式化输出
123456789-> 123,456,78912345678 -> 12,345,67812345678.123 -> 12,345,678.123
function formatMoney(num) {// 将输入的数字转化为字符串,并将此字符串拆分为整数部分和小数部分var parts = num.toString().split(".");// 对整数部分进行格式化parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");// parts[0] = parts[0].replace(/\B(\d(?=(\d{3})+(?!\d)))/g, "$1,");// 将格式化后的整数部分和小数部分重新拼接return parts.join(".");}console.log(formatMoney(123456789)); // 123,456,789console.log(formatMoney(12345678)); // 12,345,678console.log(formatMoney(12345678.123)); // 12,345,678.123
