如何编写单个正则表达式实现多可选分组的多模式文本捕获
单个正则实现方案
完全可以用单个正则覆盖所有给出的场景,利用分组可选匹配的特性就能实现,无需回退匹配第二个正则:
/^\(?([^|[\]]+)(?:\|([^[\]]+))?(?:\[([^\]]+)])?(?:[, ]+)?([^)\]]+)?\)?$/
分组说明:
- 第1组捕获
text1:匹配开头到|/[/结束位置的内容 - 第2组捕获
text2:|之后到[之前的可选内容,不存在时返回undefined - 第3组捕获
text3:方括号包裹的可选内容,不存在时返回undefined - 第4组捕获
text4:方括号/逗号之后、右括号之前的可选内容,不存在时返回undefined
优化后的解析实现
你原来的实现有两个问题:一是第一个正则用贪婪匹配.*捕获text3,会把方括号后的内容也吞入第三个分组,导致text4捕获错误;二是空字段返回空字符串的逻辑需要额外兼容。优化后的代码如下:
const items = [ "text1", "text1|text2", "text1|text2[text3]", "text1|text2[text3] text4", "(text1|text2[text3], text4)", "text1[text3]", "text1[text3], text4" ] const parse = (text) => { const match = /^\(?([^|[\]]+)(?:\|([^[\]]+))?(?:\[([^\]]+)])?(?:[, ]+)?([^)\]]+)?\)?$/.exec(text) return { text1: match?.[1] ?? '', text2: match?.[2] ?? '', text3: match?.[3] ?? '', text4: match?.[4] ?? '' }; } for(const text of items) { console.log(parse(text)); }
运行后所有测试用例都能准确提取对应字段,不会出现匹配错误的情况。
其他可选解析方案
如果后续字段规则会持续迭代,更推荐用状态机逐字符解析,比正则可维护性更高:
- 逐字符扫描,遇到
|就标记当前切换到text2的读取状态 - 遇到
[就标记当前切换到text3的读取状态,遇到]退出该状态 - 遇到
(、)、逗号直接跳过,空格根据前后内容判断是否属于字段内容
这种方案后续加字段或者改分隔符规则的时候,不需要重构整个正则表达式,修改成本更低。
内容的提问来源于stack exchange,提问作者Józef Podlecki
相关产品推荐
相关产品推荐

