首页 > 解决方案 > 如何解析使用波兰符号结构的搜索查询?

问题描述

我的应用程序有一个搜索框,它支持具有以下结构的查询:

输入: 具有以下结构的字符串:

<operand><phrase><category>  <operand><phrase><category>  ...


<operand>: can be + or - to denote include or exclude and is optional

<phrase>: can be a single word or a word or sentence surrounded by quotes

<category>: is surrounded by square brackets and can be either [c1], [c2], or [c3]

一个查询的示例:

+car "tart berries"[fruit]  -"broccoli"[vegetable] "green onion"[vegetable] pepper[vegetable]  -"my keys"[object]

期望的输出:

[
["+", "car",         ""],
["" , "tart berries","fruit"],
["-", "broccoli".,   "vegetable"],
["" , "green onion", "vegetable"],
["" , "pepper",      "vegetable"]
]

我的代码:

我使用以下正则表达式来捕获组:

let re = /([+-]?)(\w+|".+?")(\[fruit\]|\[vegetable\]|\[object\])?/gi
var str = '+car "tart berries"[fruit]  -"broccoli"[vegetable] "green onion"[vegetable] pepper[vegetable]  -"my keys"[object]'

for (const match of str.matchAll(re)) {

    console.log(match);
}

问题:

  1. 项目多次重复:
["+car", "+", "car"]
[""tart berries"[fruit]", "", ""tart berries"", "[fruit]"]
  1. 有没有办法从结果中排除引号。
"tart berries" instead of ""tart berries"" 

标签: javascriptregexparsing

解决方案


您无法摆脱正则表达式中的引号,JS 正则表达式不支持分支重置组,因此您必须对匹配项进行后处理。

此外,要仅捕获不带方括号的c1//值c2c3您需要替换(\[a]|\[b]|\[c])?为可选的非捕获组并将替代项重新分组为(?:\[(a|b|c)]).

请注意,"[^"]*"它比 更有效".+?"

您可以使用

let re = /([+-]?)(\w+|"[^"]*")(?:\[(fruit|vegetable|object)])?/gi
const rx_quotes = /^"|"$/g;
var str = '+car "tart berries"[fruit]  -"broccoli"[vegetable] "green onion"[vegetable] pepper[vegetable]  -"my keys"[object]'
let result = [];
for (const match of str.matchAll(re)) {
    let [_,x,y,z] = match;
    y = y.replace(rx_quotes,'');
    if (z === undefined) z = "";
    result.push([x,y,z]);
}
console.log(result);

正则表达式详细信息

  • ([+-]?)- 第 1 组:可选+-字符
  • (\w+|"[^"]*")- 第 2 组:一个或多个单词字符或双引号之间的字符串
  • (?:\[(fruit|vegetable|object)])?- 一个可选的非捕获组匹配 1 或 0 次出现
    • \[- 一个[字符
    • (fruit|vegetable|object)- 第 3 组:任何子串备选方案
    • ]- 一个]字符。

推荐阅读