【问题标题】:Regex nested tags正则表达式嵌套标签
【发布时间】:2017-02-17 09:53:36
【问题描述】:

我想通过函数标签用Regex解析下面的文本。

Anwers: <function>2+2
                 <function>1+3</function> 
        </function>.  
Thanks for your time. 
<function>sayGoodbye() 
         <function>10*10</function> 
         writeYourName()
</function>

下面是一个递归方法,应该将给定的文本转换为:

答案:44。 谢谢你的时间。 再见 100 条雷克斯。

private static readonly string TagFormulaStart = "<function>";
private static readonly string TagFormulaEnd = "</function>";

public static string Calculate(string formula)
{
    var pattern = string.Format("{0}(((.|\r|\n)*?)){1}", TagFormulaStart, TagFormulaEnd);
    var matches = Regex.Matches(formula, pattern);

    if (matches.Count == 0)
    {
        return formula;
    }
    else
    {
        var firstAppearanceOfTAG = matches[0].ToString();
        var formulaToCalculate = firstAppearanceOfTAG.Replace(TagFormulaStart, string.Empty).Replace(TagFormulaEnd, string.Empty);
        var result = BgProcessorLib.Evaluator.EvaluateString(formulaToCalculate, null, false);

        formula = formula.Replace(firstAppearanceOfTAG, result);

        return Calculate(formula);
    }
}

问题是我的正则表达式 /&lt;function&gt;(((.|\r|\n)*?))&lt;\/function&gt;/igm 在嵌套标签的情况下将在第一次出现函数结束标签时停止。

为了更清楚,我附上一张图片。

【问题讨论】:

  • 如果你在 C# 中工作并使用 .NET 正则表达式,那么在只支持 JS 正则表达式的站点上测试正则表达式是没有意义的。
  • 您确定要使用正则表达式解析 XML 吗?有很多现成的“轮子”,调用 XML 解析器。
  • @NikolayProkopyev 它不是 XML。
  • XML 和 HTML 不是“常规语言”(在技术意义上)。因此,一般来说,正则表达式不能处理它们(即使在它们的大规模扩展状态下,超出了正则表达式的原始概念)。请改用解析器。坚持使用正则表达式可能会有[后果[(stackoverflow.com/a/1732454/67392)。
  • @POIR:不清楚为什么输出应该有Goodbye 100 Rex.

标签: c# regex nested tags


【解决方案1】:

虽然我不建议通过 RegEx 解决这个问题,但如果你真的想这样做,你必须告诉你的 Regex 不要包含另一个开始标签,例如:

<function>((?!<function>).)*?<\/function>

警告:糟糕的表现,仅用于教育目的!

另外,你应该转义你的输入:

var pattern string.Format("{0}((?!{0}).)*?{1}", 
    Regex.Escape(TagFormulaStart), 
    Regex.Escape(TagFormulaEnd));

var matches = Regex.Matches(formula, pattern, RegexOptions.Singleline);

这不会考虑很多实际的用例,所以再说一次:我不建议在这种特殊情况下使用 RegEx。

Online-Demo
Fiddle

【讨论】:

  • “教育”提示:永远不要在模式中使用(.|\r|\n)*?。只需使用RegexOptions.Singleline,只需. 即可匹配任何字符。
  • @WiktorStribiżew 对!我完全忘记了那个^^
【解决方案2】:

关于 XML 方法。

首先,使您的源代码有效 XML,即添加周围的 &lt;root&gt; Answer &lt;function... &lt;/root&gt; 根标签。

然后使用像Linq这样的解析器

XElement root = XElement.Parse(sourceString);

foreach (var funct in root.Descendants("function")).ToList() {
   var evaluated = evaluate(funct.InnerText); // evaluate should be defined before
   funct.InnerText = evaluated;
}

var result = root.ToString();

然后你可以用正则表达式或简单的字符串替换替换所有标签(删除括号之间的所有内容)。也许,XML Linq 也有一个现成的工具,但我不知道。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多