JSON对象重构:课程数据字符串解析方案咨询
嘿,我完全懂你现在的处境——要重构暑期课程作业的JSON数据,可爬来的数据格式不对,还没法重新爬,只能硬着头皮从这些杂乱的课程字符串里抠出各个字段对吧?别慌,我给你设计一个精准又好用的正则方案,还会把每部分的逻辑讲清楚,顺便搞定那个同一个tr里有两个课程条目的边缘情况。
先拿你给的典型字符串举例:10:00 - 11:00MK4603 - LEC firstname lastname DR KBG121-12,我们需要拆分出时间、模块、类型、讲师、房间这几个核心字段,再扩展支持周数字段。
定制正则表达式
针对这个格式,我写了一个针对性的正则,能精准匹配每个字段:
(\d{2}:\d{2} - \d{2}:\d{2})([A-Z0-9]+) - (LEC|TUT) (.+?) ([A-Z]+[\d-]+)
正则分组详解
每个括号里的内容就是一个字段分组,对应关系一目了然:
- 第1组
(\d{2}:\d{2} - \d{2}:\d{2}):匹配时间范围,比如10:00 - 11:00,确保小时和分钟都是两位数字,格式完全符合你的示例。 - 第2组
([A-Z0-9]+):匹配模块代码,比如MK4603,只匹配大写字母和数字,适配常见的课程模块命名规则。 - 第3组
(LEC|TUT):精准匹配课程类型,只允许LEC或TUT,避免匹配到无关内容。 - 第4组
(.+?):非贪婪模式匹配讲师信息,比如firstname lastname DR。非贪婪的好处是会在遇到下一个符合房间格式的内容时停止,不会把房间号也包含进来。 - 第5组
([A-Z]+[\d-]+):匹配房间号,比如KBG121-12,以大写字母开头,后面跟着数字和可选的横杠,覆盖绝大多数教学楼房间编号格式。
处理多条目边缘情况(代码示例)
如果同一个HTML <tr>里有两个课程字符串,只需要给正则加上全局匹配标志g,就能循环提取所有条目。这里用JavaScript示例(你可以改成自己熟悉的语言,正则逻辑通用):
// 包含两个课程条目的示例字符串 const courseStr = "10:00 - 11:00MK4603 - LEC John Doe DR KBG121-12 13:00 - 14:00MK4603 - TUT Jane Smith DR KBG122-05"; // 带全局匹配标志的正则 const regex = /(\d{2}:\d{2} - \d{2}:\d{2})([A-Z0-9]+) - (LEC|TUT) (.+?) ([A-Z]+[\d-]+)/g; const courses = []; let match; // 循环提取所有匹配的课程条目 while ((match = regex.exec(courseStr)) !== null) { courses.push({ time: match[1], module: match[2], type: match[3], lecturer: match[4].trim(), // 去掉讲师字段前后可能的多余空格 room: match[5] }); } console.log(courses);
运行这段代码后,courses数组里就会包含两个完整的课程对象,完美解决多条目问题。
扩展:周数字段的处理
你提到需要周数字段,如果你的字符串里有类似W1-W5或W3的周数标识,可以把正则扩展一下,增加一个可选分组:
(\d{2}:\d{2} - \d{2}:\d{2})([A-Z0-9]+) - (LEC|TUT) (.+?) ([A-Z]+[\d-]+)(?: W(\d+(?:-\d+)?))?
- 新增的第6组
(\d+(?:-\d+)?):匹配周数,支持单周(比如3)或周范围(比如1-5),(?: ...)?表示这个周数部分是可选的,不会影响没有周数的字符串匹配。
对应的代码里,只需要在对象里添加week: match[6] || '无周数'即可。
小技巧:调试正则
如果你遇到格式稍微特殊的字符串,可以找个本地的正则测试工具(比如编辑器自带的正则查找功能),把示例字符串放进去,一步步调整正则的各个部分,看每个分组匹配的内容是否符合预期,这样能快速适配你的特殊场景。
如果还有其他奇怪的格式情况,随时告诉我,我帮你调整正则~
内容的提问来源于stack exchange,提问作者Lake Sereni

