![JavaScript 正则实战:用字符集 `[-:]` 匹配 hh:mm 与 hh-mm 双格式时间](http://pic.xiahunao.cn/yaotu/JavaScript 正则实战:用字符集 `[-:]` 匹配 hh:mm 与 hh-mm 双格式时间)
文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载本指南围绕 Modern JavaScript Tutorial本项目仓库中「字符集与范围Sets and ranges」章节的一道实战练习展开如何用一条正则表达式同时匹配09:00与21-30这两种两位时、两位分的常见时间格式。读完本文你将掌握字符集[...]的匹配语义、连字符-在方括号内的转义规则以及g标志与String.prototype.match的实际用法并学会用单词边界等技巧规避误匹配。任务背景同一串文本两种时间格式题目位于 9-regular-expressions/08-regexp-character-sets-and-ranges/2-find-time-2-formats/task.md要求如下时间可能是小时:分钟如09:00或小时-分钟如21-30两种格式小时和分钟都必须恰好是两位数字在字符串Breakfast at 09:00. Dinner at 21-30中期望匹配出09:00和21-30题目明确说明假定时间本身总是合法的本任务不需要过滤45:67这类非法组合后续任务会再处理时间合法性校验。题目给出的待补全模板是let regexp /your regexp/g; alert( Breakfast at 09:00. Dinner at 21-30.match(regexp) ); // 期望输出: 09:00, 21-30注意模板中已经带了g标志——这意味着要用match一次收集所有匹配项而不是只取第一个。标准答案\d\d[-:]\d\d解答见 2-find-time-2-formats/solution.md答案是let regexp /\d\d[-:]\d\d/g; alert( Breakfast at 09:00. Dinner at 21-30.match(regexp) ); // 09:00, 21-30逐段拆解这个模式模式片段含义\d\d两位数字字符类\d等价于集合[0-9]见 08 章节正文[-:]字符集匹配一个字符要么是连字符-要么是冒号:\d\d再匹配两位数字整体语义就是两位数字 连字符或冒号 两位数字恰好覆盖09:00与21-30两种写法。核心知识点 1字符集一次只匹配一个字符字符集[...]表示在给定的若干字符中任取一个。因此[-:]虽然列出两个符号但它在匹配时只消费输入中的一个字符——这正是它适合充当分隔符的原因。这一点在 08 章节正文 中有专门强调集合中字符再多对应到匹配结果中也恰好是一个字符。例如// 找 V然后 [o 或 i]然后 la alert( Voila.match(/V[oi]la/) ); // null匹配不到因为Voila中V之后是o和i两个字符而[oi]只能吃掉一个于是整个模式失败。同理我们的[-:]也只会在:与-之间二选一不会把21-30中间的横杠连同两侧数字一起吞掉。核心知识点 2方括号内连字符为何不用转义解答中特别给出了一条值得记住的规则solution.md 原文要点连字符-在方括号内具有特殊含义但只在位于其他字符之间用于定义范围如[a-z]时如此当它位于方括号的开头或结尾时就是普通字符因此无需转义。也就是说[-:]中-紧跟在左方括号[之后、不夹在两个字符中间引擎不会把它解析成范围直接按字面连字符处理。这正是本题能写出如此简洁模式的底层原因。08 章节正文 的「Escaping in […]」小节系统总结了方括号内的转义铁律符号.()在方括号内永远不需要转义连字符-在开头或结尾不转义此处不构成范围插入符^只在开头需要转义否则表示排除语义右方括号]若要按字面匹配则总是需要转义。顺带一提即使你出于保险把所有特殊字符都转义了也不会出错。例如 08 章节正文 中的对照实验// 不转义版 let regexp /[-().^]/g; alert( 1 2 - 3.match(regexp) ); // 匹配到 , - // 全部转义版同样可用 let regexp2 /[\-\(\)\.\^\]/g; alert( 1 2 - 3.match(regexp2) ); // 同样匹配到 , -本题的[-:]属于不转义版简洁且正确。扩展对比加上单词边界避免123:456误伤细心的读者会发现\d\d[-:]\d\d本身并不关心分隔符两侧是不是独立的时间在字符串Breakfast at 09:00 in the room 123:456中它会从123:456里截出23:45这个假时间。仓库中另一道同类练习 06-regexp-boundary/1-find-time-hh-mm 专门考察了这一点其要求是匹配Breakfast at 09:00 in the room 123:456.中的时间且不得匹配123:456标准答案引入了单词边界alert( Breakfast at 09:00 in the room 123:456..match( /\b\d\d:\d\d\b/ ) ); // 09:00对比可见两种需求的差异需求模式是否能拒绝123:456中的23:45本任务只要09:00和21-30允许宽松匹配\d\d[-:]\d\d不能边界任务时间前后必须是单词边界\b\d\d:\d\d\b能若把本任务升级为严格版本同样可以写成/\b\d\d[-:]\d\d\b/g在\b单词边界约束下123:456内部的子串因左侧3是单词字符而无法通过边界检查从而被正确排除。实战验证与扩展练习基础验证在浏览器控制台或 Node.js 中直接运行答案代码match配合g标志返回的数组为[09:00, 21-30]去掉g则只返回第一个09:00。混合分隔符压力测试对12-34 56:78 90-00运行/\d\d[-:]\d\d/g可得到全部三个匹配。非法时间测试按题目 P.S. 的约定45:67也会被匹配出来——这是本任务有意允许的行为时间合法性校验留给后续章节仓库中9-regular-expressions的进阶练习会逐步引入更严格的分组与回溯模式。排除范围复习同章节另一道练习 1-find-range-1 考察了[^script]排除范围的语义Java后跟一个非 s/c/r/i/p/t 中任一字符的字符可与本题的包含型集合[-:]对照学习两者正是字符集选其一与排除其一的两面。小结要同时匹配hh:mm与hh-mm一条/\d\d[-:]\d\d/g即可其核心是字符集[-:]——方括号内位于开头/结尾的连字符无需转义且集合一次只匹配一个分隔符字符若想拒绝123:456这类嵌套误匹配可升级为\b\d\d[-:]\d\d\b相关完整语法集合、范围、排除范围、转义规则、u标志下的 surrogate pair 行为见 字符集与范围章节正文。赞分享文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载相关推荐JavaScript正则表达式教程字符集合与范围匹配JavaScript正则表达式教程字符集合与范围匹配 你是否曾经遇到过这样的场景需要从复杂的文本中提取特定模式的字符但又不想为每个可能的字符都编写单独的模JavaScript 正则表达式教程字符集合与范围匹配JavaScript 正则表达式教程字符集合与范围匹配 什么是字符集合 在正则表达式中方括号 ... 表示一个字符集合它告诉正则引擎匹配其中任意一个字符文档/教程前端正则表达式实战Swift中的字符串模式匹配与验证正则表达式实战Swift中的字符串模式匹配与验证 引言 在日常开发中我们经常需要处理各种文本数据的验证和提取工作。无论是验证用户输入的邮箱格式、检查电话号码示例工程上一篇Switch本地视频播放革命wiliwili带你解锁全平台观影新体验下一篇前端开发实战笔记2019移动端适配、类型转换与 CSS 动画的踩坑与技巧总结创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考