JavaScript正则提取编号列表转数组匹配不全的问题修复
问题原因
原代码正则存在4个核心问题,导致匹配结果不符合预期:
- 单级编号匹配规则缺失:正则仅对多级编号(如
1.1)写了完整的数字+点+数字匹配逻辑,但单级编号(如1.、2.)只匹配了数字部分,没有匹配数字后面的点,导致所有一级列表项的编号都无法被识别。 - 强制要求编号后必须有空格:正则中编号和内容之间写死了
\s匹配空格,但测试用例里的1.2another item编号和内容之间没有空格,该条目会被直接跳过。 - 无法匹配换行内容:正则里的
.默认不匹配换行符\n,(.*)只能捕获同一行内编号后的内容,碰到跨多行的列表项就会直接终止匹配。 - 没有定义列表项的结束边界:原逻辑默认行尾就是列表项结束位置,没有考虑跨多行场景下,列表项内容会一直延续到下一个编号出现才结束的规则,既会漏掉多行内容,也无法正确识别后续编号。
修正方案
调整正则规则补全上述逻辑,通过循环匹配提取所有列表项,同时自动清理内容里多余的缩进、换行空白:
let input = `1. This is a text\n where each item can span over multiple lines\n 1.1 this is another item\n 1.2another item\n 2. that I want to\n extract each seperate\n item from\n 3. How can I do that?`; // 正则说明: // 1. 优先匹配x.x格式多级编号,再匹配x.格式单级编号 // 2. 编号后空格可选,兼容无空格场景 // 3. 非贪婪匹配所有字符(含换行)直到碰到下一个编号或字符串结尾 let regex = /(\d+\.\d+|\d+\.)\s?([\s\S]*?)(?=\s*(?:\d+\.\d+|\d+\.)\s?|$)/g; let listItems = []; let matchRes; while ((matchRes = regex.exec(input)) !== null) { // 清理内容里的多余换行、缩进,合并连续空白为单个空格 const content = matchRes[2].replace(/\s+/g, ' ').trim(); listItems.push(`${matchRes[1]} ${content}`.trim()); } console.log(listItems);
运行后输出结果如下,完全覆盖所有列表项:
[ '1. This is a text where each item can span over multiple lines', '1.1 this is another item', '1.2 another item', '2. that I want to extract each seperate item from', '3. How can I do that?' ]
如果需要保留
1.2another item这类编号后无空格的原始格式,只需要把正则调整为/(\d+\.\d+|\d+\.)(\s?)([\s\S]*?)(?=\s*(?:\d+\.\d+|\d+\.)\s?|$)/g,拼接时直接拼接matchRes[1] + matchRes[2] + 处理后的matchRes[3]即可。如果需要保留列表项的原始换行格式,去掉内容替换的逻辑,直接存储捕获到的原始内容即可。
内容的提问来源于stack exchange,提问作者Aman
相关产品推荐
相关产品推荐

