JavaScript解析聊天文本:拆分四字段实现聊天数据统计的正则适配问题
聊天文本结构化拆分实现方案
现有拆分逻辑的问题根源
你之前使用的/[,:\s+\-]/正则属于无差别匹配规则,只要碰到逗号、冒号、空白、连字符就直接拆分,完全没有上下文约束:既会把时间字段里和数字绑定的冒号(例如14:30)、日期字段里的连字符(例如2024-05-20)拆碎,也会把消息正文里出现的“: ”作为拆分点破坏字段结构,最终完全得不到预期的四字段结果。
核心匹配规则设计
针对你提出的两个硬性拆分要求,规则要做严格的边界约束:
- 区分两类冒号:时间字段内的冒号两侧均为数字,这类冒号不作为拆分点;仅当冒号后紧跟半角空格,且位置处于昵称段尾部时,才作为昵称和消息内容的分隔符
- 限制拆分位置:仅在行内首次出现上述“: ”的位置做拆分,后续正文内出现的同类字符全部归入消息内容字段,不触发二次拆分
具体代码实现
1. 全量内容按行拆分
对同步Ajax获取到的stringData变量,先按换行符拆分所有聊天行,过滤无效空行:
const rowList = stringData.split(/\r?\n/).filter(row => row.trim() !== '') // 可直接将测试字符串str推入rowList,验证解析逻辑 // rowList.push(str)
2. 逐行匹配结构化四字段
采用单次正则匹配直接锚定Date、Time、Name、Text四个字段,避免多次拆分带来的错位问题:
// 逐行解析的核心正则,通过命名分组直接对应结构化字段 const chatRowReg = /^(?<date>\d{4}[-/]\d{1,2}[-/]\d{1,2})\s+(?<time>\d{1,2}:\d{2}(?::\d{2})?)\s+(?<name>[^:]+?):\s(?<text>.*)$/ const structuredData = rowList.map(row => { const matchRes = row.match(chatRowReg) // 兼容无发件人的系统公告行,避免整体解析中断 if (!matchRes) { return { date: '', time: '', name: '未识别/系统消息', text: row.trim(), parseError: true } } return { date: matchRes.groups.date, time: matchRes.groups.time, name: matchRes.groups.name.trim(), text: matchRes.groups.text, parseError: false } })
方案适配性说明
- 不会误拆时间内的冒号:
time字段的匹配规则为连续数字+冒号+连续数字(例如14:32:05),这类位置的冒号无后置空格,和作为拆分点的:(冒号+空格)属于完全独立的匹配场景,不会被混淆 - 不会被正文内容干扰:
name字段匹配时会自动停在第一个冒号位置,后续只要满足“冒号后接空格”的条件,就会将剩余整段内容全部归入text字段,哪怕text内部多次出现“: ”也不会触发额外拆分
3. 后续统计能力适配
拿到structuredData的结构化数组后,可直接基于字段做聚合统计,无需回溯原始聊天文本:
- 基础统计:对每个条目下的
text字段做长度累加即可得到总字数;对text按空白符分割并过滤空片段,统计非空片段数量即可得到总词数 - 维度聚合:以
name、date字段为分组键,分别累加对应维度下的总字数、总词数,即可满足按发送人、按日期的统计需求
内容的提问来源于stack exchange,提问作者Dumitru Daniel
相关产品推荐
相关产品推荐

