用正则捕获组解析算术表达式:The Modern JavaScript Tutorial 分组实战
文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载导读本文完整讲解 Modern JavaScript TutorialThe Modern JavaScript Tutorial 仓库正则表达式章节中的实战任务——用正则解析形如1.2 * 3.4、-3 / -6的算术表达式从中提取出第一个数字、运算符、第二个数字。读者将掌握数字/运算符正则的构造方法、match返回数组的捕获组编号规则、非捕获组(?:...)与命名组(?name...)的区别最终实现一个可复用的parse(expr)函数。任务目标解析一个算术表达式本题要求详见 task.md一个算术表达式由两个数字和一个运算符组成例如1 21.2 * 3.4-3 / -6-2 - 2运算符只能是四种之一、-、*、/表达式开头、结尾以及各部分之间允许出现任意数量的空格。需要编写函数parse(expr)它接收一个表达式字符串返回包含 3 个元素的数组序号元素说明1第一个数字整数或小数可带负号2运算符、-、*或/3第二个数字整数或小数可带负号使用示例let [a, op, b] parse(1.2 * 3.4); alert(a); // 1.2 alert(op); // * alert(b); // 3.4第一步构造数字与运算符的子模式数字模式-?\d(\.\d)?数字模式来自本组章节的上一道题见 03-find-decimal-numbers/solution.mdlet regexp /-?\d(\.\d)?/g; let str -1.5 0 2 -123.4.; alert( str.match(regexp) ); // -1.5, 0, 2, -123.4逐段拆解片段含义-?可选的负号?表示出现 0 或 1 次\d一个或多个数字整数部分(\.\d)?可选的小数部分一个点号后跟一个或多个数字整体可缺省该模式能同时覆盖整数、小数与负数。运算符模式[-*/]运算符用字符类表示[-*/]。这里有一个关键细节连字符-必须放在方括号的最前面。因为连字符在字符类中间位置会被解释为范围例如[a-z]表示从a到z的区间而我们想要的是字面字符-所以必须把它放在首位或转义。另外在 JavaScript 的正则字面量/.../中斜杠/需要转义为\/否则会提前结束正则字面量。第二步组装完整正则并验证匹配把数字 空格 运算符 空格 数字组合起来其中\s*表示可选的空白字符空格、制表符等出现 0 次或多次pattern:-?\d(\.\d)?\s*[-*/]\s*-?\d(\.\d)?整个模式由三部分构成中间用\s*连接-?\d(\.\d)?—— 第一个数字[-*/]—— 运算符-?\d(\.\d)?—— 第二个数字。为了让每个部分成为结果数组中的独立元素需要把各部分用**括号捕获组**包起来捕获组原理详见主章节 article.md括号除了分组让量词作用于整体还会把匹配到的内容按编号存入结果数组pattern:(-?\d(\.\d)?)\s*([-*/])\s*(-?\d(\.\d)?)运行验证let regexp /(-?\d(\.\d)?)\s*([-*\/])\s*(-?\d(\.\d)?)/; alert( 1.2 12.match(regexp) );第三步读懂match返回的结果数组由于正则没有g标志str.match(regexp)返回第一个匹配对应的数组此规则见 article.md 中 Parentheses contents in the match 一节索引0是完整匹配1、2…… 依次是各捕获组的内容组编号按左括号从左到右的顺序计数。对1.2 12匹配(-?\d(\.\d)?)\s*([-*/])\s*(-?\d(\.\d)?)的结果逐项分析数组索引值对应模式说明result[0]1.2 12完整匹配整个表达式result[1]1.2第 1 组(-?\d(\.\d)?)第一个数字含小数部分result[2].2第 2 组(\.\d)?第一个数字的小数部分result[3]第 3 组([-*\/])运算符result[4]12第 4 组(-?\d(\.\d)?)第二个数字result[5]undefined第 5 组(\.\d)?第二个数字的小数部分缺省故为undefined第 5 项为undefined正是可选组的典型行为即使某个组因量词(…)?而没有参与匹配结果数组中仍保留对应位置值为undefined参见 article.md 的 Optional groups 一节。第四步清理结果——shift()与非捕获组(?:...)我们需要的是数字与运算符而不是完整匹配、也不是小数部分因此对结果做两步清洁去掉完整匹配数组第一项就是完整匹配用result.shift()移除排除小数部分的捕获第 2 组与第 4 组(\.\d)?属于多余信息。给它们加上?:改为非捕获组(?:\.\d)?——括号仍然把内容分组、让?量词作用于整体但不再进入编号、不占用结果数组的位置原理详见 article.md 的 Non-capturing groups with ?: 一节。最终的正则变为pattern:(-?\d(?:\.\d)?)\s*([-*/])\s*(-?\d(?:\.\d)?)此时match返回数组[-1.23 * 3.45, -1.23, *, 3.45]shift()后正好剩下三个目标元素。最终方案parse(expr)函数function parse(expr) { let regexp /(-?\d(?:\.\d)?)\s*([-*\/])\s*(-?\d(?:\.\d)?)/; let result expr.match(regexp); if (!result) return []; result.shift(); return result; } alert( parse(-1.23 * 3.45) ); // -1.23, *, 3.45实现要点if (!result) return [];当match找不到匹配时返回null函数应返回空数组作为兜底result.shift()移除数组第一项完整匹配非捕获组(?:\.\d)?既保留了小数部分的可选语义又不污染结果数组。替代方案命名捕获组(?name...)除非捕获组外还可以用命名组让代码更可读。命名组通过在左括号后加?name实现匹配结果存放在.groups属性中见 article.md 的 Named groups 一节function parse(expr) { let regexp /(?a-?\d(?:\.\d)?)\s*(?operator[-*\/])\s*(?b-?\d(?:\.\d)?)/; let result expr.match(regexp); return [result.groups.a, result.groups.operator, result.groups.b]; } alert( parse(-1.23 * 3.45) ); // -1.23, *, 3.45命名方案无需再手动shift()直接从result.groups按名字取值语义清晰适合分组较多的场景。注意命名组同样参与编号也占数组索引位只是额外提供了.groups的访问途径而(?:...)非捕获组既不参与编号、也没有名字。延伸解析表达式串与替换若要匹配字符串中的所有表达式而不仅是第一处需要加g标志并使用str.matchAll(regexp)它会返回可迭代对象每个匹配仍包含完整匹配、捕获组与index/input属性详见 article.md 的 matchAll 一节若想用捕获组内容做字符串重排可用str.replace(regexp, $n)引用编号组、$name引用命名组——例如把捕获到的算术式重新格式化为无空格形式。小结数字子模式-?\d(?:\.\d)?可同时覆盖整数、小数与负数连字符-在字符类中需置于首位斜杠/在正则字面量中需转义捕获组按左括号从左到右编号match无g标志在索引0返回完整匹配其后依次是各组内容可选组未参与匹配时值为undefined用result.shift()移除完整匹配用(?:...)非捕获组排除多余分组二者结合即可得到干净的三元素结果命名组(?name...)通过result.groups.name取值的写法是更可读的替代方案完整的parse(expr)实现与逐步推导均可在仓库 04-parse-expression 与 task.md 中对照学习正则分组的系统讲解见 article.md。赞分享文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载相关推荐使用正则表达式捕获组解析算术表达式JavaScript 中 parse(expr) 函数实战使用正则表达式捕获组解析算术表达式JavaScript 中 parse expr 函数实战 导读 本篇文章以现代 JavaScript 教程Modern J文档/教程前端JavaScript 正则表达式中的分组捕获技术详解JavaScript 正则表达式中的分组捕获技术详解 正则表达式Regular Expression是处理文本的强大工具而分组捕获Grouping anJavaScript 正则表达式中的捕获组详解JavaScript 正则表达式中的捕获组详解 正则表达式是 JavaScript 中强大的文本处理工具而捕获组则是正则表达式中一个非常重要的概念。本文将深入文档教程前端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考