满口金牙 2022-07-26 15:00 采纳率: 91.5%
浏览 67
已结题

js 验证 excel 函数四则运算式的 方法,请教

目的: 验证 excel 函数四则运算式的 合法性的 方法,

如 b1+a12*(a1+a2) + round(2/3,2)
如: if( a1!=0,12,34)
校验这个 式子是不是 对的

下面的代码是论坛找的修改了一下,,其实有很多问题,很多情况没考虑到.感觉有些复杂

比如 不是自定义的funcName 函数中的, 这个判断 怎么加到正则里
_ if (/[\+\-\*\/]{1}[^\d\(]/.test(string)) {console.log('运算符后不是数字,也不是自定义的函数'); return false};_

function expressionCheck(string) {
        // 先把 A12, ab12 等单元格名称,替换成数字
        string = string.replace(/\b[a-z]{1,2}\d{1,2}\b/gi, '1')
        const funcName = {
            'sum': 1,
            'abs': 1,
            'round': 1,
        };
        let stack
        // 剔除空白符
        string = string.replace(/\s/g, '');
        // 错误情况,空字符串
        if ("" === string) return false;
        // 错误情况,运算符连续
        if (/[\+\-\*\/]{2,}/.test(string)) return false;
**错误情况,运算符后不是数字, 不是(, 且不是 funcName中的函数名称 ,这个地方没想到怎么弄???**
        if (/[\+\-\*\/]{1}[^\d\(]/.test(string)) {console.log('运算符后不是数字,也不是函数'); return false};
        // 错误情况,空括号
        if (/\(\)/.test(string)) return false;
        // 错误情况,(后面是运算符 
        if (/\([\+\-\*\/]/.test(string)) return false;
        // 错误情况,)前面是运算符
        if (/[\+\-\*\/]\)/.test(string)) return false;
        // 错误情况,(前面不是运算符
        if (/[^\+\-\*\/]\(/.test(string)) return false;
        // 错误情况,)后面不是运算符
        if (/\)[^\+\-\*\/]/.test(string)) return false;
        // 错误情况,括号不配对
        stack = [];
        for (var i = 0, item; i < string.length; i++) {
            item = string.charAt(i);
            if ('(' === item) {
                stack.push('(');
            } else if (')' === item) {
                if (stack.length > 0) {
                    stack.pop();
                } else {
                    return false;
                }
            }
        }
        // 错误情况,双引号不配对
        stack = [];
        for (var i = 0, item; i < string.length; i++) {
            item = string.charAt(i);
            if (item == '"') {
                stack.push('"');
            }
        }
        if (0 !== stack.length % 2) return false;
        // 错误情况,单引号不配对
        stack = [];
        for (var i = 0, item; i < string.length; i++) {
            item = string.charAt(i);
            if (item == "'") {
                stack.push("'");
            }
        }
        if (0 !== stack.length % 2) return false;
        // 错误情况,不是函数的字符串
        const tmpStr = string.replace(/[\(\)\+\-\*\/]{1,}/g, '`');
        const array = tmpStr.split('`');
        for (let i = 0, item; i < array.length; i++) {
            item = array[i];
            // 如果是引号中的字符串,忽略掉
            if (item.charAt(0) == '"' && item.charAt(item.length - 1) == '"'
                || item.charAt(0) == "'" && item.charAt(item.length - 1) == "'") {
                continue
            }
            if (/[A-Z]/i.test(item) && 'undefined' === typeof (funcName[item])) {
                return false;
            }
        }
        console.log('验证成功')
        return true;

    }
    expressionCheck("'我的")

  • 写回答

3条回答 默认 最新

  • CSDN专家-showbo 2022-07-26 17:56
    关注

    这涉及编译原理了。。全部还给了老师。。嘿嘿。。。如果是一段完整的表达式,可以提取变量出来做初始化,然后用try..catch和eval来判断,但是相关自定义函数需要在当前代码中定义,比如round

    
        var kvKeywods = { 'if': 1 };//关键字过滤
        function round() { return 1;}
        function check(exp) {
            try {
                var reval = /([a-z_][a-z\d_]+)/g, m;
                //正则分析变量处理初始化成1
                while (m = reval.exec(exp)) {
                    var Var = m[1];
                    if (!kvKeywods[Var]) {//不是关键字
                        if (!window[Var]) {//未全局定义过,进行赋值
                            window[Var] = 1;
                        }
                    }
                }
                var result = eval(exp);//执行表达式,如果不正确会执行catch
    
                console.log('表达式没问题', result)
    
                return true;
            }
            catch (e) {
                console.log(e);
                return false;
            }
        }
        var exps = [`b1 + a12 * (a1 + a2) + round(2 / 3, 2)`, ` if (a1 != 0, 12, 34)`]
        exps.forEach(exp => console.log(check(exp)))
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 8月4日
  • 已采纳回答 7月27日
  • 修改了问题 7月26日
  • 修改了问题 7月26日
  • 展开全部

悬赏问题

  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效