如何用正则解析含引号的复杂分隔属性字符串?
问题描述
给定字符串:
def str='prop1: value1, prop2: value2;value3, prop3:"test:1234, test1:23;45, test2:34;34", prop4: "test, 66;77, 888"'
期望解析为以下属性-值对:
prop1: value1 prop2: value2;value3 prop3: test:1234, test1:23;45, test4:34;34 prop4: test, 66;77, 888
尝试用Groovy正则提取带引号的键值对时,仅能匹配prop3,无法匹配prop4,代码如下:
def str='prop1: value1, prop2: value2;value3, prop3:"test:1234, test1:23;45, test4:34;34", prop4: "test, 66;77, 888"' def regex = /(\w+):"(.*)"[,\s]|$/ def m = (str =~ regex) (0..<m.count).each{ println("${m[it][1]}=${m[it][2]}") }
运行结果:
prop3=test:1234, test1:23;45, test2:34;34 null=null
问题分析与解决
1. 无法匹配prop4的原因
你的正则存在两个核心问题:
- 未处理冒号与引号间的空格:
prop4的格式是prop4: "...",而正则(\w+):"要求冒号后直接跟引号,忽略了中间的空格,导致匹配失败。 - 正则逻辑冗余:末尾的
[,\s]|$写法混乱,且(.*)贪婪匹配可能引发意外匹配,但核心问题是空格未兼容。
修正后的带引号键值匹配正则及代码:
def str='prop1: value1, prop2: value2;value3, prop3:"test:1234, test1:23;45, test4:34;34", prop4: "test, 66;77, 888"' def regex = /(\w+):\s*"(.*?)"(?:,|$)/ def m = (str =~ regex) (0..<m.count).each{ println("${m[it][1]}=${m[it][2]}") }
运行结果:
prop3=test:1234, test1:23;45, test4:34;34 prop4=test, 66;77, 888
2. 一次正则扫描完成全量解析
可以通过分支正则同时匹配带引号和不带引号的键值对,无需拆分两次。正则逻辑:
(\w+):匹配属性名:\s*:匹配冒号及后续可选空格(?:"(.*?)"|([^,]+)):分支匹配值——要么是带引号的非贪婪匹配内容,要么是到下一个逗号前的所有字符(?:,|$):匹配结尾的逗号或字符串结束(非捕获组,避免冗余捕获)
实现代码:
def str='prop1: value1, prop2: value2;value3, prop3:"test:1234, test1:23;45, test4:34;34", prop4: "test, 66;77, 888"' def regex = /(\w+):\s*(?:"(.*?)"|([^,]+))(?:,|$)/ def m = (str =~ regex) (0..<m.count).each { idx -> def key = m[idx][1] // 合并两个捕获组的结果,两种匹配场景只会有一个有值 def value = m[idx][2] ?: m[idx][3].trim() println("${key}: ${value}") }
运行结果完全符合期望:
prop1: value1 prop2: value2;value3 prop3: test:1234, test1:23;45, test4:34;34 prop4: test, 66;77, 888
内容的提问来源于stack exchange,提问作者mike01010
相关产品推荐
相关产品推荐

