如何从字符串中提取所有数字?附测试案例及问题排查
看起来你在提取字符串中的数字时碰到了几个典型的正则匹配坑,我来逐个帮你拆解原因,再给出靠谱的解决方案。
首先明确你的需求:从类似7nr-6p、12c-18L这类混杂字母、符号和数字的字符串里,提取所有独立数字,最终得到像{7,6}、{12,18}这样的数字集合。
先解答你遇到的几个异常问题:
问题1:返回
{7,"","",6,""},出现空字符串
这是因为你用的正则大概率带了*量词(比如(\d*)),*的含义是「匹配0次或多次」。当正则遇到非数字字符时,它会匹配到「0个数字」,也就是空字符串,所以结果里就混入了这些无效的空值。把量词换成+(匹配1次或多次),就能只捕获至少包含一个数字的结果,彻底避免空字符串。问题2:返回
{7},匹配未继续找后面的6
这通常是没开启全局匹配模式导致的。比如在JavaScript里,用match(/\d+/)而不带g标志的话,只会返回第一个匹配到的数字;在Python里如果用re.search()而非re.findall(),也只会找到第一个匹配项。开启全局匹配后,正则才会遍历整个字符串,找出所有符合条件的数字。问题3:返回
7,,,6,这类带空分隔的结果
应该是用了split方法按单个非数字字符分割(比如split(/\D/))。举个例子,7nr-6p里的n、r、-、p都是单独的非数字字符,每一个都会作为分隔符,分割后自然会产生空的间隔。改成按「一个或多个非数字字符」分割(比如split(/\D+/)),就能把连续的非数字字符当成一个分隔符,得到干净的数字数组。
靠谱的解决方案
直接用全局匹配一个或多个数字的正则,是最简洁可靠的方式,下面给你几个常用语言的示例:
JavaScript 示例
const extractNumbers = (str) => { // 全局匹配所有连续数字,转成数字类型后转成集合 const nums = str.match(/\d+/g)?.map(Number) || []; return new Set(nums); }; // 测试你的输入 console.log(extractNumbers("7nr-6p")); // Set(2) {7, 6} console.log(extractNumbers("12c-18L")); // Set(2) {12, 18} console.log(extractNumbers("12nr-24L")); // Set(2) {12, 24}
Python 示例
import re def extract_numbers(s): # 找到所有连续数字,转成整数后转成集合 nums = re.findall(r'\d+', s) return set(int(num) for num in nums) # 测试 print(extract_numbers("7nr-6p")) # {7, 6} print(extract_numbers("12c-18L")) # {12, 18}
这个方法的核心是/\d+/g(或Python里的r'\d+'):
\d匹配单个数字+确保匹配至少一个数字,避免空结果g(JS里)开启全局匹配,找出所有符合条件的数字序列
这样就能精准提取出所有数字,不会再出现你遇到的那些异常情况啦。
内容的提问来源于stack exchange,提问作者user3871

