在JavaScript中评估给定的布尔表达式字符串

6

我有一个包含布尔逻辑的字符串,类似于:

var test = "(true)&&(false)&&!(true||true)"

如何在JavaScript中评估此字符串以获取布尔值false的好方法是什么?

  1. 我知道我们可以使用eval()或new Function()..-但这是安全的方法吗?
  2. 我猜另一个选择是编写自定义解析器。作为JS的新手,这会需要很大的努力吗?我找不到任何布尔逻辑表达式解析器的示例
  3. 还有其他替代方案吗?

3
"(true)&&(false)&&!(true||true)" 的来源是什么? - Rayon
我正在解析服务器的响应,并根据一些逻辑构建该字符串。 - akoy
您可以在应用逻辑后将服务器返回的数据作为布尔值使用。为什么要将它转换为字符串? - Gibbs
如果语法像 "(1)&(0)&!(1||1)"(所有令牌只有1个字符),那么解析将更容易。 - Oriol
使用 new Function() 没有意义,因为你实际上不需要一个函数,你只需要表达式的结果。 - nnnnnn
显示剩余7条评论
5个回答

3
只要您能保证安全,我认为您可以使用eval。也许在执行eval之前进行处理?
var test = "(true)&&(false)&&!(true||true)" 

var safe = test.replace(/true/ig, "1").replace(/false/ig, "0");

var match = safe.match(/[0-9&!|()]*/ig);

if(match) {
   var result = !!eval(match[0]);
}

2
如果内容安全策略已禁用代码评估,则无法使用。 - Alexander O'Mara

1
JavaScript有一个三元运算符可以使用:
var i = result ? 1 : 0;

在这里,结果是一个布尔值,可以是TrueFalse
因此,在此操作后,您的问题将类似于这样。
(1)&(0)&!(1||1)

我希望你现在能更好地评估这个布尔逻辑。


1

您可以使用eval,例如:eval("(true)&&(false)&&!(true||true)");


0

试试这段代码

function processExpression(expr)
{
  while (expr.indexOf("(" ) != -1 )
  {
    expr = expr.replace(/\([\w|]+\)/g, function(matched){ return processBrace(matched)});
  }
  return expr = processBrace( "(" + expr + ")" );
}
function processBrace(str)
{
    return str.substring(1).slice(0,-1).split(/(?=&|\|)/).map(function(value,index,arr){ 
        if ( index != 0 && index%2 == 0 ) { return arr[index-1] + value } else if(index==0){return value;} else {return ""}
    }).filter(function(val){return val.length > 0}).reduce(function(prev,current){
        var first = Boolean(prev);
        var operator = current.substring(0,2);
        var operand = current.substring(2); 
        while ( operand.indexOf("!") != -1 )
        {
           var boolval = operand.match(/\w+/)[0] == "false"; //flip the value by comparing it with false
           var negations = operand.match(/\W+/)[0];
           operand = negations.substring(1) + boolval;
        }
        var second = operand == "true";
        var output = operator == "&&" ? (first && second) : (first || second); 
        return output;
    });
}

演示

    function processExpression(expr)
    {
      while (expr.indexOf("(" ) != -1 )
      {
     expr = expr.replace(/\([\w|]+\)/g, function(matched){ return processBrace(matched)});
      }
      return expr = processBrace( "(" + expr + ")" );
    }
    function processBrace(str)
    {
     return str.substring(1).slice(0,-1).split(/(?=&|\|)/).map(function(value,index,arr){ 
      if ( index != 0 && index%2 == 0 ) { return arr[index-1] + value } else if(index==0){return value;} else {return ""}
     }).filter(function(val){return val.length > 0}).reduce(function(prev,current){
      var first = Boolean(prev);
      var operator = current.substring(0,2);
      var operand = current.substring(2); 
      while ( operand.indexOf("!") != -1 )
      {
         var boolval = operand.match(/\w+/)[0] == "false"; //flip the value by comparing it with false
         var negations = operand.match(/\W+/)[0];
         operand = negations.substring(1) + boolval;
      }
      var second = operand == "true";
      var output = operator == "&&" ? (first && second) : (first || second); 
      return output;
     });
    }


var example1 = "(true)&&(false)&&!(true||true)";
document.body.innerHTML += example1 + " -- " + processExpression(example1);


-1

尝试在三元运算符条件中使用 "".match()

"(true)&&(true)&&!(true||true)".match(/false/ig)?false:true

该语句中有一个 ! 符号。 - thealpha93
感谢您的评论,但是贬低自己思考的评论并不是正确的方式,请您保持积极态度,不要贬低我的评论。 实际上,我在我的评论中没有写!,我只是从提问者那里复制了它。谢谢。 - Muhammad Kamran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接