使用零宽度正向后视断言在正则表达式上难以理解

时间:2009-09-02 18:54:12

标签: c# regex

我有一个字符串,我想找到所有不属于 HTML标记的字符。

忽略CDATA等,这应该很简单:找到任何“>”没有“<”的字符在它之前,还是有另一个“>”他们之间。

这是我提出的第一个尝试解决方案:

 (?<=(^|>)[^<]*)>

认为这应该寻找任何“&gt;”哪里没有“&lt;”它左边的字符,或者回到字符串的开头,或者回到之前的“&gt;”。

我也尝试过消极地说:

 (?<!<[^>]*)>

即,“&gt;”那也不是“&lt;”之前除非之后只有非“&gt;”字符。

我怀疑我只是在谈论看起来如何工作。

单元测试:

 No match in: <foo>
 No match in: <foo bar>
 Match in: <foo> bar>
 Match in: foo> bar
 Match in: >foo
 Two matches in: foo>>
 Two matches in: <foo> >bar>

使用案例:我正在从接受某些HTML标记的类似wiki的表单字段中清除HTML,但是用户并不是非常精通HTML,有时会输入未转义的“&gt;”和“&lt;”实际小于和大于含义的文字。我的目的是用HTML实体替换它们,但前提是它们不是HTML标记的一部分。我知道他们有可能输入“Heigh is&lt; 10 and&gt; 5”这样的文字,这会破坏这一点,但这是一个我可以解决或生活的边缘情况。

2 个答案:

答案 0 :(得分:3)

这比起初看起来要棘手得多(正如你所发现的那样)。从另一个方向来看它要容易得多:使用一个正则表达式来匹配HTML标签或尖括号。如果它是您找到的标签,请将其重新插入;否则你转换它。带有MatchEvaluator参数的Replace方法适用于此:

static string ScrubInput(string input)
{
  return Regex.Replace(input, @"</?\w+>|[<>]", GetReplacement);
}

static string GetReplacement(Match m)
{
  switch (m.Value)
  {
    case "<":
      return "&lt;";
    case ">":
      return "&gt;";
    default:
      return m.Value;
  }
}

您会注意到我的代码正则表达式 - </?\w+> - 比您的更严格。我不知道我的是否完全符合您的需求,但我建议不要使用<[^<>]+> - 它会找到"if (x<3||x>9)"之类的匹配。

答案 1 :(得分:0)

获取expresso,这是处理和编写正则表达式的好工具

说实话,我不知道你是否可以写一个来做你需要的东西 不要忘记,有些html标签不需要关闭才能成为有效的html,有些是在xhtml中自行关闭。

eg. <hr>, <br/>, <p>, <li> <img> or <img /> etc

你可能会更好,只需保留有效标签列表,更改所有&lt;和&gt; &lt;&gt;的符号不属于有效代码。