JavaScript中使用正则提取带β前缀的嵌套大括号内内容
JavaScript提取β{...}结构中嵌套大括号内的内容
问题描述
现有如下JavaScript字符串:
var str = "β{;{9}/{(n-7)(n-8)}} ≤ β{;{18({3}/{2})}/{(n-8) 8} ≥ ;{36}/{9.8} ;{9}/{4}}";
需要提取所有以β开头的β{...}结构中,{和}之间的内容(包含嵌套大括号),期望结果:
str1 = ";{9}/{(n-7)(n-8)}" str2 = ";{18({3}/{2})}/{(n-8) 8} ≥ ;{36}/{9.8} ;{9}/{4}"
尝试过PHP的递归正则表达式:
\{((?:[^{}]++|\{(?1)\})++)\}
但该正则在JavaScript中无法生效,因为JS正则引擎不支持(?1)这类递归引用语法。
补充测试示例:
- 示例1:
输入:
期望提取内容:testinput = "β{test{test{12351}}{a+b}{1/2}}"test{test{12351}}{a+b}{1/2}(注:原示例输出标注为{test{test{12351}}{a+b}{1/2}}β,此处按实际提取需求修正) - 示例2:
输入:
期望提取内容:testinput = "β{test}"test
解决方案
方法1:手动遍历字符串解析(兼容性拉满)
由于JS正则不支持原生递归匹配嵌套结构,手动遍历跟踪大括号层级是最稳妥的方案:
function extractBetaContent(str) { const results = []; let index = 0; const len = str.length; while (index < len) { // 定位β的位置 const betaIndex = str.indexOf('β', index); if (betaIndex === -1) break; // 定位β后的第一个左大括号 const openBraceIndex = str.indexOf('{', betaIndex + 1); if (openBraceIndex === -1) break; let currentIndex = openBraceIndex + 1; let braceLevel = 1; // 初始层级为1(已找到一个左大括号) // 遍历直到找到匹配的右大括号 while (currentIndex < len && braceLevel > 0) { const char = str[currentIndex]; if (char === '{') braceLevel++; else if (char === '}') braceLevel--; currentIndex++; } // 层级归0时,提取左右大括号之间的内容 if (braceLevel === 0) { const content = str.slice(openBraceIndex + 1, currentIndex - 1); results.push(content); } index = currentIndex; } return results; } // 测试使用 const str = "β{;{9}/{(n-7)(n-8)}} ≤ β{;{18({3}/{2})}/{(n-8) 8} ≥ ;{36}/{9.8} ;{9}/{4}}"; const [str1, str2] = extractBetaContent(str); console.log(str1); // 输出: ;{9}/{(n-7)(n-8)} console.log(str2); // 输出: ;{18({3}/{2})}/{(n-8) 8} ≥ ;{36}/{9.8} ;{9}/{4} // 测试示例1 const testinput1 = "β{test{test{12351}}{a+b}{1/2}}"; console.log(extractBetaContent(testinput1)[0]); // 输出: test{test{12351}}{a+b}{1/2} // 测试示例2 const testinput2 = "β{test}"; console.log(extractBetaContent(testinput2)[0]); // 输出: test
方法2:ES2018+正则递归(简洁但有环境要求)
如果你的运行环境支持ES2018及以上(如Chrome 62+、Node.js 10+),可以用(?R)递归引用语法实现:
const regex = /β\{((?:[^{}]|(?R))*)\}/g; const str = "β{;{9}/{(n-7)(n-8)}} ≤ β{;{18({3}/{2})}/{(n-8) 8} ≥ ;{36}/{9.8} ;{9}/{4}}"; const results = []; let match; while ((match = regex.exec(str)) !== null) { results.push(match[1]); } console.log(results); // 输出: [ ";{9}/{(n-7)(n-8)}", ";{18({3}/{2})}/{(n-8) 8} ≥ ;{36}/{9.8} ;{9}/{4}" ]
说明:
(?R)会重复整个正则的匹配逻辑,以此实现嵌套大括号的匹配。
总结
- 手动遍历法兼容性最好,适用于所有JS环境,逻辑清晰易调试;
- 正则法更简洁,但依赖ES2018+特性,适合现代浏览器或Node.js项目。
内容的提问来源于stack exchange,提问作者Students World
相关产品推荐
相关产品推荐

