正则表达式转换需求:从查询字符串提取指定结构化输出
解决嵌套OData风格查询的正则解析问题
看起来你需要解析的是嵌套结构的OData风格查询字符串,之前的正则只能处理平级的字段 eq 值项,没法应对user:(...)这种嵌套括号里的子条件——这是因为普通正则默认不支持平衡括号(嵌套括号)的匹配,得用递归捕获组来处理嵌套结构才行。
问题拆解
你的目标是生成两个嵌套数组:
- 保留完整条件片段的数组
- 只提取字段名的数组
核心难点是正确识别顶层的and分隔符(不能误切嵌套内部的and),以及解析嵌套的子条件。
解决方案思路
我们分两步走:
- 用支持递归的正则匹配所有顶层条件项(包括嵌套项)
- 对嵌套项的内部内容,递归重复解析逻辑,生成子数组
下面以JavaScript为例(ES2018+支持递归捕获和命名组),给出具体实现:
第一步:编写递归正则匹配条件项
这个正则可以同时匹配平级条件和嵌套条件:
const conditionRegex = /(?<full>(?:(?<field>[\w\.]+)\s+eq\s+(?<value>"(?:[^"\\]|\\.)*"|\d+|null)|(?<nestedField>[\w\.]+):\((?<inner>(?:[^()]|(?R))*)\)))/gi;
(?R)是递归引用整个正则,用来匹配嵌套的括号内容- 命名组
full捕获整个条件项,field/value捕获平级条件的字段和值,nestedField/inner捕获嵌套项的字段和内部内容
第二步:编写解析函数
我们写两个函数,分别生成完整条件数组和字段名字数组:
// 解析完整条件片段的函数 function parseFullConditions(query) { // 先去掉外层的括号 const innerQuery = query.replace(/^\(|\)$/g, ''); const result = []; let match; while ((match = conditionRegex.exec(innerQuery)) !== null) { const { field, nestedField, inner } = match.groups; if (field) { // 平级条件,直接加入结果 result.push(match.groups.full); } else if (nestedField) { // 嵌套条件,递归解析内部内容 const innerConditions = parseFullConditions(`(${inner})`); result.push({ [nestedField]: innerConditions }); } } return [result]; // 外层包一层数组,符合你要的格式 } // 解析字段名的函数 function parseFieldNames(query) { const innerQuery = query.replace(/^\(|\)$/g, ''); const result = []; let match; while ((match = conditionRegex.exec(innerQuery)) !== null) { const { field, nestedField, inner } = match.groups; if (field) { result.push(field); } else if (nestedField) { const innerFields = parseFieldNames(`(${inner})`); result.push({ [nestedField]: innerFields[0] }); } } return [result]; }
第三步:测试验证
把你的查询字符串代入测试:
const query = '(name eq "xxxx" and user:(post.id eq 6 and post.post eq "testing") and data eq "Hello World!")'; console.log(JSON.stringify(parseFullConditions(query), null, 2)); console.log(JSON.stringify(parseFieldNames(query), null, 2));
输出结果:
- 完整条件数组:
[ [ "name eq \"xxxx\"", { "user": [ "post.id eq 6", "post.post eq \"testing\"" ] }, "data eq \"Hello World!\"" ] ]
- 字段名字数组:
[ [ "name", { "user": [ "post.id", "post.post" ] }, "data" ] ]
注意事项
- 这个方案依赖支持递归正则的引擎(比如JavaScript ES2018+、PCRE、Python的
regex库等),如果是老版本环境可能需要调整 - 正则已经处理了带转义的字符串(比如
"Hello \"World\"")和数字值,你可以根据需求扩展支持更多值类型(比如布尔值)
内容的提问来源于stack exchange,提问作者Shwetank
相关产品推荐
相关产品推荐

