React输入框BODMAS表达式正则验证问题求助
解决React输入框的数学表达式验证与计算问题
用单一正则完全验证符合BODMAS规则的数学表达式(尤其是带嵌套括号的)非常困难——普通正则对嵌套结构的支持有限,你之前的两个正则要么不兼容括号,要么逻辑冗余导致误判。下面给你一套更可靠的方案:
1. 先做括号平衡检查
括号不匹配是最容易排查的错误,先写一个简单函数验证括号成对:
function isBracketsBalanced(str) { let balance = 0; for (const char of str) { if (char === '(') balance++; if (char === ')') balance--; if (balance < 0) return false; // 右括号提前出现,直接不合法 } return balance === 0; // 最终左右括号数量必须相等 }
2. 结合正则做基础合法性过滤
先过滤掉非法字符,再排除明显的结构错误(比如连续运算符、运算符开头/结尾等):
function isValidExpression(str) { const trimmed = str.replace(/\s/g, ''); // 先去掉所有空格,方便后续检查 // 1. 只允许数字、运算符、括号、小数点 if (!/^[\d+\-*/().]+$/.test(trimmed)) return false; // 2. 验证括号平衡 if (!isBracketsBalanced(trimmed)) return false; // 3. 禁止连续运算符(比如5++3、5*-3) if (/([+\-*/]){2,}/.test(trimmed)) return false; // 4. 禁止以运算符开头或结尾(括号除外) if (/^[+\-*/]|[+\-*/]$/.test(trimmed)) return false; // 5. 禁止括号与运算符直接相邻(比如(+5)、5*)) if (/(\([+\-*/])|([+\-*/]\))/.test(trimmed)) return false; // 6. 禁止多个小数点连续或出现在错误位置 if (/(\.\d*\.)|(^\.)|(\.$)/.test(trimmed)) return false; return true; }
3. 安全计算表达式结果
直接用eval存在安全风险(恶意输入可能执行代码),推荐用new Function替代,或者使用专门的数学库(比如Math.js):
function calculateExpression(expr) { if (!isValidExpression(expr)) throw new Error('表达式不合法'); try { // 去掉空格后构建计算函数,仅返回表达式结果 const calc = new Function(`return ${expr.replace(/\s/g, '')}`); const result = calc(); if (isNaN(result)) throw new Error('计算结果无效'); return result; } catch (e) { throw new Error('计算失败:' + e.message); } }
补充说明
- 这套方案比单一正则更可靠,能覆盖括号不匹配、非法字符、结构错误等常见问题
- 如果需要支持负数(比如
-5+3),只需调整规则,允许表达式开头为负号,或括号内开头为负号 - 若要支持更复杂的表达式(比如平方、开方),建议直接使用成熟的数学表达式解析库(如Math.js),避免自己造轮子
内容的提问来源于stack exchange,提问作者ayesigwar
相关产品推荐
相关产品推荐

