reactjs 我正在尝试用javascript编写regex,在求值之前验证用户是否输入了有效的BODMAS字符串

inb24sb2  于 2022-12-18  发布在  React
关注(0)|答案(1)|浏览(74)

我试图呈现一个react input元素,它可以接受一个数字或一个字符串,并使用BODMAS操作(如(5*3)+8)对其进行求值。我希望首先验证BODMAS字符串,因此我试图提出一个正则表达式来验证字符串是否有效,例如,它捕获了一些缺少括号的内容,如(5*3 +8
到目前为止我有两个表达式

const regex = /^(?:\s*\d+(?:\s*[+*/-]\s*\d+)*\s*)$/;

这一个不会验证类似(5+30)*8的内容,而另一个

const regex2 = /^\(*(\d+(\.\d+)*|\((\d+(\.\d+)*|\(*(\d+(\.\d+)*|\((\d+(\.\d+)*|[\+-\/\*]))*\)*)*\)*)*[\+-\/\*]*)+\)*$/

这个函数返回为无效,我是regex的新手,我想我可能遗漏了一些东西。

dgsult0t

dgsult0t1#

最好的方法是使用解析器。
但是如果愿意,您可以迭代地简化输入字符串,直到不能删除更多的括号。
下面的代码片段是它的一个实现。用户的输入是真实的验证的:

function validate(expr) {
    expr = expr.replace(/\d+(\.\d+)?/g, "0")    // Simplify numbers to "0"
               .replace(/\s+/g, "")             // Remove white space
               .replace(/\B[+-]+(?=[0(])/g, "") // Remove unary operators (minus and plus)
               .replace(/[+*\/^-]/g, "-");      // Simplify binary operators to "-"
    for (let i = expr.length + 1; i > expr.length; ) {
        i = expr.length;
        expr = expr.replace(/\(0(-0)*\)/g, "0"); // Remove inner parentheses
    }
    return /^0(-0)*$/.test(expr);
}

// I/O management

const input = document.querySelector("input");
const refresh = () => input.className = validate(input.value) ? "ok" : "error";
input.oninput = refresh;
refresh();
.error { background: orange }
.ok { background: lightgreen }
Expression: <input type="text">

对于解析表达式,使用Shunting yard algorithm,可能需要一些扩展来支持函数和更多,例如我的实现here

相关问题