复杂的正则表达式或字符串解析

时间:2013-07-11 09:25:30

标签: c# regex

我们正在尝试使用网址进行复杂的查询和过滤 我设法让一些更简单的parst工作使用表达式树和混合使用正则表达式和字符串操作,但后来我们看了一个更复杂的字符串示例

 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*”

从那里我可以删除项目[0]部分以获得

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

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

正则表达式看起来像

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

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

3 个答案:

答案 0 :(得分:2)

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

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

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

来解析XML节点
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*”</node>
  </andNode>
</node>

答案 1 :(得分:1)

我知道您需要在filterstring中指定的值。

我的解决方案是这样的:

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);
}

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

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

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

我希望这能帮助你完成任务。

答案 2 :(得分:0)

我认为你应该为此做一个合适的解析器 - 它实际上会变得更简单,更具可扩展性并且在将来节省时间和麻烦。您可以使用任何现有的解析器生成器,例如IronyANTLR