2

我们正在尝试使用 url 进行复杂的查询和过滤。
我设法使用表达式树以及正则表达式和字符串操作的混合来获得一些更简单的解析,但随后我们查看了一个更复杂的字符串示例

 var filterstring="(|(^(categoryid:eq:1,2,3,4)(categoryname:eq:condiments))(description:lk:”*and*”))";

我希望能够将其解析为部分,但也允许它是递归的。我希望输出看起来像:

   item[0] (^(categoryid:eq:1,2,3,4)(categoryname:eq:condiments)
   item[1] description:lk:”*and*”

从那里我可以剥离 item[0] 部分以获得

categoryid:eq:1,2,3,4
categoryname:eq:condiments

目前我正在使用 RegEx 和字符串来查找 | ^ 知道它是 AND 还是 OR,RegEx 匹配括号并且适用于单个项目,当我们嵌套我正在努力的值时。

正则表达式看起来像

@"\((.*?)\)"

我需要一些使用正则表达式来匹配嵌套括号的方法,我们将不胜感激。

4

3 回答 3

2

您可以将字符串转换为有效的 XML(只是一些简单的替换,无需验证):

var output = filterstring
    .Replace("(","<node>")
    .Replace(")","</node>")
    .Replace("|","<andNode/>")
    .Replace("^","<orNode/>");

然后,您可以使用例如System.Xml.Linq.

XDocument doc = XDocument.Parse(output);

根据您的评论,以下是您重新排列 XML 以获得所需包装的方式:

foreach (var item in doc.Root.Descendants())
{
    if (item.Name == "orNode" || item.Name == "andNode")
    {
        item.ElementsAfterSelf()
            .ToList()
            .ForEach(x =>
            {
                x.Remove();
                item.Add(x);
            });
    }
}

这是生成的 XML 内容:

<node>
  <andNode>
    <node>
      <orNode>
        <node>categoryid:eq:1,2,3,4</node>
        <node>categoryname:eq:condiments</node>
      </orNode>
    </node>
    <node>description:lk:”*and*”&lt;/node>
  </andNode>
</node>
于 2013-07-11T10:12:21.013 回答
1

我了解您想要过滤字符串中指定的值。

我的解决方案是这样的:

NameValueCollection values = new NameValueCollection();
foreach(Match pair in Regex.Matches(@"\((?<name>\w+):(?<operation>\w+):(?<value>[^)]*)\)"))
{
     if (pair.Groups["operation"].Value == "eq")
         values.Add(pair.Groups["name"].Value, pair.Groups["value"].Value);
}

正则表达式理解一个(名称:操作:值),它不关心所有其他东西。

运行此代码后,您可以获得如下值:

values["categoryid"]
values["categoryname"]
values["description"]

我希望这对你的追求有所帮助。

于 2013-07-11T10:55:31.017 回答
0

我认为你应该为此做一个适当的解析器——它实际上最终会更简单、更可扩展,并在未来为你节省时间和麻烦。您可以使用任何现有的解析器生成器,例如IronyANTLR

于 2013-07-11T12:13:10.623 回答