实现基于正则匹配区间的字符串分段截断功能
实现JavaScript函数truncateBetweenPattern:按规则截断匹配模式间的字符串
需求规则
- 若目标截断部分的长度≤指定
padding值,保持原内容不变 - 字符串开头的非匹配部分:从左侧截断,保留右侧
padding长度的内容,前置分隔符sep - 字符串结尾的非匹配部分:从右侧截断,保留左侧
padding长度的内容,后置分隔符sep - 两个匹配模式中间的非匹配部分:从中间截断,前后各保留
padding长度的内容,中间插入分隔符sep - 未找到任何匹配模式时,直接返回原字符串
完整实现代码
const str = 'xxxxx<mark>foo</mark>xx<mark>bar</mark>xxxxxxxxx<mark>baz</mark>xxxxxxxx' const truncateBetweenPattern = (str, pattern, padding = 0, sep = '...') => { // 修正原模式的贪婪匹配问题,转为非贪婪匹配避免跨标记匹配 const adjustedPattern = pattern.replace(/\.\+/g, '.+?'); // 转为全局正则,确保匹配所有符合项 const regex = new RegExp(adjustedPattern, 'g'); // 拆分字符串,保留匹配的标记块(捕获组会让split保留分隔符) const parts = str.split(regex); // 无匹配项时直接返回原字符串 if (parts.length === 1) return str; return parts.reduce((result, part, index) => { // 奇数索引为匹配到的内容,直接拼接 if (index % 2 === 1) { return result + part; } const partLength = part.length; // 长度不超过padding,直接保留 if (partLength <= padding) { return result + part; } // 根据位置处理非匹配块 if (index === 0) { // 开头部分:保留右侧padding长度,前置分隔符 return `${result}${sep}${part.slice(partLength - padding)}`; } else if (index === parts.length - 1) { // 结尾部分:保留左侧padding长度,后置分隔符 return `${result}${part.slice(0, padding)}${sep}`; } else { // 中间部分:前后各取padding长度,中间加分隔符 const leftSegment = part.slice(0, padding); const rightSegment = part.slice(partLength - padding); return `${result}${leftSegment}${sep}${rightSegment}`; } }, ''); } // 传入原模式,代码会自动处理为非贪婪匹配 const pattern = '(<mark>.+</mark>)'; const result = truncateBetweenPattern(str, pattern, 3); console.log(result === '...xxx<mark>foo</mark>xx<mark>bar</mark>xxx...xxx<mark>baz</mark>xxx...'); // 输出 true
关键细节说明
- 正则修正:原示例中的
(<mark>.+</mark>)是贪婪匹配,会错误地从第一个<mark>匹配到最后一个</mark>,代码中自动将.+替换为.+?实现非贪婪匹配,确保每个标记块独立匹配。 - 字符串拆分逻辑:利用正则捕获组的特性,
split方法会将匹配到的标记块和非标记块交替存入数组,方便后续分别处理。 - 位置判断:通过数组索引判断非匹配块是开头、中间还是结尾,分别应用对应的截断规则。
- 边界处理:覆盖了无匹配项、非匹配块长度不足
padding等边界场景,确保逻辑鲁棒性。
内容的提问来源于stack exchange,提问作者Louis Grellet
相关产品推荐
相关产品推荐

