☰
现代 JavaScript 教程正则实战:用捕获组匹配十进制数字(整数、浮点数与负数)
2026/10/9 5:27:54 网站建设 项目流程
  • 文档
  • 教程
  • 前端

【免费下载链接】zh.javascript.info

现代 JavaScript 教程(The Modern JavaScript Tutorial),以最新的 ECMAScript 规范为基准,通过简单但足够详细的内容,为你讲解从基础到高阶的 JavaScript 相关知识。

项目地址:https://gitcode.com/gh_mirrors/zh/zh.javascript.info
点击查看免费下载

本文基于《现代 JavaScript 教程(zh.javascript.info)》中「找出所有数字」这一经典练习,从题目要求出发,逐步拆解正则表达式/-?\d+(\.\d+)?/g的每个组成部分:字符类、量词、点号转义、可选负号与捕获组。结合仓库中 字符类、量词 与 捕获组 章节的讲解,以及同一章节内其他练习对该模式的复用,深入说明其原理、边界情况与实战扩展,帮助你掌握"一次性匹配整数、浮点数和负数"这类真实文本解析需求的标准写法。

1. 题目回顾:找出字符串中的所有十进制数字

练习 03-find-decimal-numbers/task.md 的要求非常明确:

编写一个正则表达式,找出所有十进制数字,包括整数、浮点数和负数。

给定的用例字符串与期望输出:

let regexp = /你的正则表达式/g; let str = "-1.5 0 2 -123.4."; alert( str.match(regexp) ); // -1.5, 0, 2, -123.4

注意这里的三个隐含要求:

  1. 整数:如0、2,没有小数点;
  2. 浮点数:如-1.5、-123.4,带小数部分;
  3. 负数:如-1.5、-123.4,以负号开头;
  4. 字符串末尾有一个孤立的小数点(-123.4.中的最后一个.),它不属于任何数字,不应被匹配。

题目刻意把这个"孤立点"放在用例里,就是考察你对"点号必须转义、且小数部分必须至少有一位数字"这一细节的理解。

2. 标准答案与逐步拆解

练习的标准解答 03-find-decimal-numbers/solution.md 给出了简洁优雅的模式:

let 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+ 量词+
\.转义的点号,匹配字面意义上的小数点点在正则中需转义
(\d+)?可选的"点后数字",整体作为一个单位捕获组 + 量词?

2.1\d+:匹配整数部分

\d是 JavaScript 正则中的数字字符类,匹配从0到9的任意一位数字,这一点在 字符类 一章中有详细说明。单独一个\d只能匹配一位数字,加上量词+(等价于{1,},表示"一个或多个")之后,\d+就能匹配任意长度的整数序列。

在 量词 章节中同样可以看到这样的基础用法:

let str = "+7(903)-123-45-67"; alert( str.match(/\d+/g) ); // 7,903,123,45,67

这正是"数字序列"的标准写法。

2.2\.:小数点必须转义

在正则表达式中,点号.是一个特殊字符类,匹配"除换行符之外的任意字符"(见 字符类 的"点匹配任何字符"一节)。因此如果要匹配字面意义上的小数点,必须写作\.,否则\d+.\d+会错误地匹配像1x5这样中间夹着任意字符的内容。

对比一下 量词 章节中给出的"浮点数"初版模式:

alert( "0 1 12.345 7890".match(/\d+\.\d+/g) ); // 12.345

\d+\.\d+能匹配12.345,但它强制要求小数部分存在,无法匹配整数0或2——这正是本练习需要在它基础上扩展的原因。

2.3(\d+)?:捕获组让小数部分整体可选

把\.\d+用括号括起来并加上?,即(\.\d+)?,含义是"小数点加数字序列这个整体,出现零次或一次"。这正是 捕获组 章节强调的两个作用之一:

如果我们将量词放在括号后,则它将括号视为一个整体。

如果不加括号写成\.\d+?,?只会作用于紧邻的\d,语义完全不同。括号在这里的作用是改变量词的作用范围,把"点号 + 数字"绑定成一个不可分割的单位。

2.4-?:可选负号

模式最开头的-?用量词?表示"零个或一个负号",使得正数与负数都能被匹配,同时不会要求每个数字都带负号。

3. 匹配过程与结果验证

对字符串"-1.5 0 2 -1234."运行/-?\d+(\.\d+)?/g,正则引擎从左到右扫描:

  • -1.5:-匹配可选负号,1匹配\d+,.5匹配(\.\d+)?→ 完整匹配-1.5;
  • 0:无负号,0匹配\d+,小数部分缺失 → 匹配0;
  • 2:同理匹配2;
  • -1234:匹配-1234,此时(\.\d+)?是可选的,引擎尝试匹配末尾的.,但后面没有数字,\.\d+无法成立,于是放弃小数部分 → 匹配-1234;
  • 末尾孤立的.被跳过,因为\.必须紧跟至少一位数字才能构成小数部分。

最终str.match(regexp)返回数组["-1.5", "0", "2", "-1234"],与题目期望完全一致。

值得注意的一个细节是:当正则带有g修饰符时,str.match返回的是所有完整匹配项组成的数组,不会包含捕获组的内容。这一点在 捕获组 的"带有组搜索所有匹配项:matchAll"一节中有明确说明。如果你不仅需要匹配到的数字本身,还需要提取"整数部分"和"小数部分"等组内内容,应当改用str.matchAll(regexp),它会为每个匹配项返回包含groups信息的完整数组。

4. 边界情况与潜在陷阱

4.1 不会匹配以点开头的小数

\d+强制要求小数点之前至少有一位数字,因此像.5这种省略整数部分的写法不会被匹配(只会匹配到其中的5)。如果业务场景需要支持这种形式,需要额外处理。

4.2 孤立小数点会被正确跳过

如题目用例-1234.末尾的.,因为\.\d+要求点后至少一位数字,孤立点无法构成小数部分,正则引擎会在整数部分结束后停止匹配,这正是标准答案的巧妙之处。

4.3 如需整词匹配可加\b

在纯数字提取场景下,-?\d+(\.\d+)?已经足够。但如果要避免从abc123def这类字符串中截取出123(例如验证一个字符串本身是否是合法数字),可以结合 锚点 章节介绍过的^...$或词边界\b来收紧匹配范围。同章节的 检查 MAC 地址练习 就展示了用^[0-9a-f]{2}(:[0-9a-f]{2}){5}$/i配合^...$进行整体校验的思路。

5. 同章节复用:这个模式是"表达式解析"的基础模块

这个十进制数字模式并非孤立练习——在同一个 捕获组 章节的 解析算术表达式练习 中,它被直接复用来解析形如"1.2 + 12"的算式:

let regexp = /(-?\d+(\.\d+)?)\s*([-+*\/])\s*(-?\d+(\.\d+)?)/;

其解题说明中明确写道:"匹配数字的正则表达式:-?\d+(\.\d+)?,我们在上一题创建了这个表达式。"这说明本章节的练习设计是递进式的:先掌握"一个数字"的匹配,再把它嵌套进更大的模式,并用括号让每个部分(第一个数字、运算符、第二个数字)成为结果数组中的独立元素。

在 解析表达式练习 的完整解法中还展示了两个进阶技巧,与本主题直接相关:

  • 用(?:\.\d+)?这种非捕获组(见 捕获组 的"非捕获组 ?:"一节)排除不需要的小数部分结果,让result数组只保留真正关心的数字与运算符;
  • 用result.shift()移除数组第 0 项(完整匹配),从而得到干净的操作数列表:
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

可以看到,本练习的-?\d+(\.\d+)?加上一层括号包装后,立刻变成了可复用的"数值 token"。

6. 从单题到体系:相关的正则知识点地图

围绕这个练习,可以把整个 正则表达式 章节的相关知识点串成一条学习路径:

知识点章节与本练习的关联
字符类\d字符类\d是数字匹配的基础
量词+、?、{n}量词+匹配多位数字,?让负号/小数部分可选
转义\.正则转义让点号匹配字面小数点
捕获组(...)捕获组(\.\d+)?把小数部分绑定为一个整体
锚点^...$、词边界\b锚点、词边界用于整体校验场景
matchAll与命名组捕获组提取每个匹配的内部结构

7. 总结

本练习的标准答案/-?\d+(\.\d+)?/g虽然只有短短一行,却浓缩了 JavaScript 正则中最核心的几个概念:

  • 字符类\d匹配数字;
  • 量词+匹配"一个或多个",?让负号-?与小数部分(\.\d+)?变为可选;
  • 点号转义\.保证匹配的是字面小数点;
  • 捕获组(...)把"点号 + 数字"绑定成整体,从而允许对整个小数部分应用量词。

掌握这行模式之后,你就可以自然过渡到 解析算术表达式 这类更复杂的实战,以及 捕获组 章节中编号组、命名组、matchAll、替换引用$n/$<name>和(?:...)非捕获组等进阶能力,形成完整的正则实战知识闭环。

  • 文档
  • 教程
  • 前端

【免费下载链接】zh.javascript.info

现代 JavaScript 教程(The Modern JavaScript Tutorial),以最新的 ECMAScript 规范为基准,通过简单但足够详细的内容,为你讲解从基础到高阶的 JavaScript 相关知识。

项目地址:https://gitcode.com/gh_mirrors/zh/zh.javascript.info
点击查看免费下载

相关推荐

上一篇:NixOS 16.03 "Emu" 发布说明全解读:核心升级、新增模块与破坏性变更迁移指南
下一篇:Flet 视频全屏按钮 VideoFullscreenButton:内置按钮栏项的参数定制与全屏模式实战指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询