正在验证查询参数并使用正则表达式对其进行解析



我是regex的新手,你能告诉我如何使用以下所有组合的查询参数吗。

(ParamName=Operator:ParamValue(是我的一组查询参数值。这将与分开;(AND(或,(or(和我想将它们分组在大括号内。如以下示例

例如:http://,host:port>/get?search=(日期=gt:2020-02-06T000:00:00.000Z;(名称=eq:测试,部门=合作:生产((此处的日期应大于2020-02-06,name=测试或部门包含生产。如何解析这些查询参数。请提出建议。

谢谢,Vijay

所以,我用JavaScript编写了一个解决方案,但经过一些研究,它也应该适用于其他语言。

这是一个相当多的代码,但你想要实现的并不是非常容易!

下面是代码,它已经被彻底评论了,但如果你有什么不明白的地方,请走开,我很乐意回答你:(

//
// The 2 first regexes are a parameter, which looks like date=gt:2020-02-06T00:00:00.000Z for example.
// The difference between those 2 is that the 1st one has **named capture group**
//      For example '(?<operator>...)' is a capture group named 'operator'.
//      This will come in handy in the code, to keep things clean
//
const RX_NAMED_PARAMETER = /(?:(?<param>w+)=(?<operator>w+):(?<value>[w-:.]+))/
const parameter = "((\w+)=(\w+):([\w-:.]+)|(true|false))"
//
// The 3rd parameter is an operation between 2 parameters
//
const RX_OPERATION = new RegExp(`\((?<param1>${parameter})(?:(?<and_or>[,;])(?<param2>${parameter}))?\)`, '');
//                                   '---------.---------'  '-------.------'  '----------.---------' 
//                                       1st parameter          AND or OR          2nd parameter
my_data = {
date: new Date(2000, 01, 01),
name: 'Joey',
department: 'Production'
}
/**
* This function compates the 2 elements, and returns the bigger one.
* The elements might be dates, numbers, or anything that can be compared.
* The elements **need** to be of the same type
*/
function isGreaterThan(elem1, elem2) {
if (elem1 instanceof Date) {
const date = new Date(elem2).getTime();
if (isNaN(date))
throw new Error(`${elem2} - Not a valid date`);
return elem1.getTime() > date;
}
if (typeof elem1 === 'number') {
const num = Number(elem2);
if (isNaN(num))
throw new Error(`${elem2} - Not a number`);
return elem1 > num;
}
return elem1 > elem2;
}
/**
* Makes an operation as you defined them in your
* post, you might want to change that to suit your needs
*/
function operate(param, operator, value) {
if (!(param in my_data))
throw new Error(`${param} - Invalid parameter!`);
switch (operator) {
case 'eq':
return my_data[param] == value;
case 'co':
return my_data[param].includes(value);
case 'lt':
return isGreaterThan(my_data[param], value);
case 'gt':
return !isGreaterThan(my_data[param], value);
default:
throw new Error(`${operator} - Unsupported operation`);
}
}
/**
* This parses the URL, and returns a boolean
*/
function parseUri(uri) {
let finalResult;
// As long as there are operations (of the form <param1><; or ,><param2>) on the URL
while (RX_OPERATION.test(uri)) {
// We replace the 1st operation by the result of this operation ("true" or "false")
uri = uri.replace(RX_OPERATION, rawOperation => {
// As long as there are parameters in the operations (e.g. "name=eq:Bob")
while (RX_NAMED_PARAMETER.test(rawOperation)) {
// We replace the 1st parameter by its value ("true" or "false")
rawOperation = rawOperation.replace(RX_NAMED_PARAMETER, rawParameter => {
const res = RX_NAMED_PARAMETER.exec(rawParameter);
return '' + operate(
res.groups.param,
res.groups.operator,
res.groups.value,
);
// The "res.groups.xxx" syntax is allowed by the
// usage of capture groups. See the top of the file.
});
}

// At this point, the rawOperation should look like
// (true,false) or (false;false) for example
const res = RX_OPERATION.exec(rawOperation);
let operation;
if (res.groups.param2 === undefined)
operation = res.groups.param1; // In case this is an isolated operation
else
operation = res.groups.param1 + ({',': ' || ', ';': ' && '}[res.groups.and_or]) + res.groups.param2;
finalResult = eval(operation);
return '' + finalResult;
});
}
return finalResult;
}
let res;
res = parseUri("http://,host:port>/get?search=(date=gt:2020-02-06T00:00:00.000Z;(name=eq:Test,department=co:Prod))");
console.log(res);
res = parseUri("http://,host:port>/get?search=(date=lt:2020-02-06T00:00:00.000Z)");
console.log(res);

最新更新