我想评估表达式以检查真实性。
用户以
的形式给我表达x == y || a == (c + 3)
或
y >= 4
我只将eval用于:
expression.replace(/[^|()\d\+-><=!&]/g, '');
eval(expression);
现在用户想给我设置包含表达式,如:
5 ∈ y || 3 ∉ y
y
是一个数组。处理该问题的最佳安全方法是什么?
编辑:感谢您的帮助,仔细阅读答案很难决定选择哪个/更好。
答案 0 :(得分:2)
只需检查自己是否包含Repo.insert! %Language{
page: "accounts",
code: "en-us",
mode: "all",
language: { "username_email" : "Username or email address",
"password" : "Password",
"invalid_username_password" : "Invalid username or password"
}
}, prefix: :lookups
,就可以用add_filter('wp_insert_post_data', 'delete_invalid_posts', 99);
function delete_invalid_posts($data) {
$false_titles = array("*****", "******");
$title_arr = explode(' ', $data['post_title']);
$found = array_intersect($false_titles, $title_arr);
if (!empty($found)) {
$data['post_status'] = 'trash';
}
return $data;
}
或eval
替换包含测试。为了实现您可以按名称访问集合,可以将它们分组为对象true
,其中键是名称,值是集合本身(请参见下面的示例):
纳入测试:
false
排除测试:
sets
示例:
var newString = string.replace(/(\S+)\s*∈\s*(\S+)/g, function(match, item, set) {
var theActualSet = ...; // get the actual set using 'set'
return theActualSet.includes(+item);
});
现在可以轻松进行评估而无需担心,只需除去var newString = string.replace(/(\S+)\s*∉\s*(\S+)/g, function(match, item, set) {
var theActualSet = ...; // get the actual set using 'set'
return !theActualSet.includes(+item);
});
和文字var sets = {
y: [1, 2, 3, 4, 5]
};
var string = "5 ∈ y || 3 ∉ y";
var newString = string.replace(/(\S+)\s*∈\s*(\S+)/g, function(match, item, set) {
var theActualSet = sets[set];
return theActualSet && theActualSet.includes(+item);
});
newString = newString.replace(/(\S+)\s*∉\s*(\S+)/g, function(match, item, set) {
var theActualSet = sets[set];
return theActualSet && !theActualSet.includes(+item);
});
console.log("The original string: '" + string + "'");
console.log("The result string: '" + newString + "'");
console.log("The result: " + eval(newString));
和|()\d\+-><=!&
以外的任何内容,然后使用true
即可得出评估。
注意:您可以使用false
和eval
来代替1
和0
,以便更轻松地删除不需要的字符:{ {1}}
答案 1 :(得分:1)
实际上很难用a E b
替换b.includes(a)
,因为您必须注意操作员的先行性。因此,唯一的方法似乎是实现自己的解析器:
const diad = (char, operation) => input => {
// If the operator doesnt exist, don't evaluate
if(!input.includes(char))
return input;
return input.split(char)
.map(evaluate) // deep first
.reduce(operation); // left to right
};
const bracketsFirst = input => {
const opening = input.lastIndexOf("("); // the most inner one
const closing = input.indexOf(")", opening);
if(opening === -1 || closing === -1) // no brackets, don't evaluate here
return input;
const before = input.slice(0, opening);
const after = input.slice(closing + 1);
const middle = input.slice(opening + 1, closing);
return before + evaluate(middle) + after; // just evaluate the thing in the brackets
};
let context = {};
const evaluate = input => [
bracketsFirst,
// Boolean algebra
diad("||", (a, b) => a || b), // lowest operator predescendence
diad("&&", (a, b) => a && b),
// Comparison:
diad("==", (a, b) => a === b),
diad("!=", (a, b) => a != b),
diad("<=", (a, b) => a <= b),
diad(">=", (a, b) => a >= b),
diad("<", (a, b) => a < b),
diad(">", (a, b) => a > b),
// Math:
diad("+", (a, b) => a + b),
diad("-", (a, b) => a - b),
diad("*", (a, b) => a * b),
diad("/", (a, b) => a / b),
// The custom operator:
diad("E", (a, b) => b.includes(a)),
// Booleans
a => a.trim() === "true" ? true : a,
a => a.trim() === "false" ? false : a,
// Number literals & Identifiers
a => +a || context[a.trim()] || a,
a => { throw Error("Unknown:" + a) }
].reduce((out, fn) => typeof out === "string" ? fn(out) : out, input);
因此您可以这样做:
context.a = [1,2,3];
context.one = 1;
evaluate("1 E a || 5 E a"); // false
evaluate("one == 1(5 - 5) - 9"); // true :)