Java正则表达式:提取带引号值的键值对及无等号键处理
键值对提取正则解决方案
需求回顾
需要从包含不规则空格的字符串中提取键值对:
- 键后带
=(前后可跟任意空格):若值被单/双引号包裹,取引号内内容;否则取到下一个空格为止 - 键后无
=:对应值为null
正则表达式
可以用全局匹配的交替正则,覆盖两种场景:
(\S+?)\s*=\s*(?:"([^"]*)"|'([^']*)'|(\S+))|(\S+)(?!\s*=)
正则拆解
- 带值的键值对分支:
(\S+?)\s*=\s*(?:"([^"]*)"|'([^']*)'|(\S+))(\S+?):非贪婪匹配键(直到遇到=为止的非空白字符)\s*=\s*:匹配=前后的任意空格(?:"([^"]*)"|'([^']*)'|(\S+)):分支匹配三种值类型:"([^"]*)":双引号包裹的内容(捕获组2)'([^']*)':单引号包裹的内容(捕获组3)(\S+):无引号的连续非空白值(捕获组4)
- 无值的键分支:
(\S+)(?!\s*=)(\S+):匹配非空白键(?!\s*=):负向预查,确保键后没有跟着=(避免误判带值的键)
匹配结果处理逻辑
遍历所有匹配项:
- 若捕获组1有值(带值的键):取捕获组2/3/4中第一个非空的内容作为值
- 若捕获组5有值(无值的键):对应值为
null
示例验证(Python代码)
import re def extract_kv(s): pattern = r'(\S+?)\s*=\s*(?:"([^"]*)"|(\S+)|'([^']*)')|(\S+)(?!\s=)' matches = re.findall(pattern, s) result = {} for match in matches: if match[0]: # 带值的键,取第一个非空的捕获组(组2、3、4) value = match[1] or match[2] or match[3] result[match[0]] = value elif match[4]: # 无值的键 result[match[4]] = 'null' # 格式化为要求的字符串 return '{' + ', '.join([f'{k}={v}' for k, v in result.items()]) + '}' # 测试示例1 print(extract_kv('key=false hotel = trivago foo cool=\'tr ue\' feels="good"')) # 输出: {key=false, hotel=trivago, foo=null, cool=tr ue, feels=good} # 测试示例2 print(extract_kv('example with a lot of words. Makes=sense.')) # 输出: {example=null, with=null, a=null, lot=null, of=null, words.=null, Makes=sense.} # 测试示例3 print(extract_kv('Did=you know that=I like= "cod ing"')) # 输出: {Did=you, know=null, that=I, like=cod ing}
原正则问题分析
你之前写的([a-zA-Z0-9]+)\s*[= ]+(?![^"']*["'])存在几个问题:
- 仅匹配了键和
=/空格,没有捕获值的部分,自然拿不到group(2) [= ]+会匹配连续的=或空格,不符合=作为键值分隔符的逻辑- 负向预查的逻辑无法正确识别引号包裹的值,导致匹配范围错误
内容的提问来源于stack exchange,提问作者Allmighty Fishmonger
相关产品推荐
相关产品推荐

