如何编写Regex提取字符串中所有连续数字子串?
用正则提取字符串的所有连续子串
当然可以实现这个需求!常规的正则匹配会消耗字符,没办法重复匹配同一位置的内容,所以我们得借助零宽度正向先行断言(positive lookahead)来搞定——它不会消耗字符串里的字符,能让我们在每个字符位置上捕获从该位置开始的所有可能长度的连续子串。
1. 编写目标正则
针对字符串 "12345",可以使用以下正则表达式:
(?=(.{1,5}))
(?=...)是正向先行断言:它会检查当前位置后方是否存在匹配内容,但不会移动正则的匹配指针,这样就能在同一位置多次匹配不同长度的子串.{1,5}表示匹配1到5个任意字符(这里都是数字),刚好覆盖目标字符串的所有可能连续子串长度
2. 获取并整理匹配结果
这个正则本身匹配的是零宽度的位置,所以我们需要提取断言内捕获的内容。以JavaScript为例,代码如下:
const input = "12345"; const regex = /(?=(.{1,5}))/g; const result = []; let match; // 遍历所有匹配,收集捕获组的内容 while ((match = regex.exec(input)) !== null) { if (match[1]) { result.push(match[1]); } } // 按子串长度从小到大排序,同长度按起始位置从左到右排序 result.sort((a, b) => { if (a.length !== b.length) { return a.length - b.length; } return input.indexOf(a) - input.indexOf(b); }); console.log(result); // 输出:["1","2","3","4","5","12","23","34","45","123","234","345","1234","2345","12345"]
3. 通用化适配
如果你的输入字符串长度不固定,可以用更通用的正则(适用于任意长度的数字字符串):
(?=(.{1,}))
注意:这个正则会匹配到空字符串(当指针走到字符串末尾时),所以收集结果时需要过滤掉空值。
原理补充
正向先行断言的核心价值在于它的零宽度特性:正则匹配指针不会因为断言而移动,所以能在字符串的每个位置(包括开头前、字符间隙、末尾后)都进行检查,每次检查时捕获从当前位置开始的所有可能长度的子串,最终覆盖所有连续子串的可能性。
内容的提问来源于stack exchange,提问作者Lucas Andrade
相关产品推荐
相关产品推荐

