【问题标题】:Why is a left parenthesis being escaped in this Regex?为什么在这个正则表达式中左括号被转义?
【发布时间】:2010-09-19 09:35:08
【问题描述】:

我正在使用此处的 HTML 清理白名单代码:
http://refactormycode.com/codes/333-sanitize-html

我需要添加“字体”标签作为附加标签来匹配,所以我尝试在<img标签检查之后添加这个条件

if (tagname.StartsWith("<font"))
{
    // detailed <font> tag checking
    // Non-escaped expression (for testing in a Regex editor app)
    // ^<font(\s*size="\d{1}")?(\s*color="((#[0-9a-f]{6})|(#[0-9a-f]{3})|red|green|blue|black|white)")?(\s*face="(Arial|Courier New|Garamond|Georgia|Tahoma|Verdana)")?\s*?>$
    if (!IsMatch(tagname, @"<font
                            (\s*size=""\d{1}"")?
                            (\s*color=""((#[0-9a-f]{6})|(#[0-9a-f]{3})|red|green|blue|black|white)"")?
                            (\s*face=""(Arial|Courier New|Garamond|Georgia|Tahoma|Verdana)"")?
                             \s*?>"))
    {
        html = html.Remove(tag.Index, tag.Length);
    }
}

除了上述条件之外,我的代码与我链接到的页面中的代码几乎相同。当我尝试在 C# 中对此进行测试时,它会抛出一个异常“Not enough )'s”。我数过括号数次,并通过一些基于 Javascript 的在线正则表达式测试器运行表达式,但似乎没有一个告诉我任何问题。

我是否在我的正则表达式中遗漏了导致括号转义的内容?我需要做什么来解决这个问题?

更新
经过大量的试验和错误,我记得# 符号是正则表达式中的注释。解决此问题的关键是转义 # 字符。万一其他人遇到同样的问题,我已经包含了我的修复(只是转义 # 符号)

if (tagname.StartsWith("<font"))
{
    // detailed <font> tag checking
    // Non-escaped expression (for testing in a Regex editor app)
    // ^<font(\s*size="\d{1}")?(\s*color="((#[0-9a-f]{6})|(#[0-9a-f]{3})|red|green|blue|black|white)")?(\s*face="(Arial|Courier New|Garamond|Georgia|Tahoma|Verdana)")?\s*?>$
    if (!IsMatch(tagname, @"<font
                            (\s*size=""\d{1}"")?
                            (\s*color=""((\#[0-9a-f]{6})|(\#[0-9a-f]{3})|red|green|blue|black|white)"")?
                            (\s*face=""(Arial|Courier\sNew|Garamond|Georgia|Tahoma|Verdana)"")?
                             \s*?>"))
    {
        html = html.Remove(tag.Index, tag.Length);
    }
}

【问题讨论】:

  • 您的更新仅适用于指定了 IgnorePatternWhitespace 选项的情况......这是我在没有回复的情况下询问的 IsMatch 代码......即您没有向我们展示导致问题的代码。
  • 顺便说一句:您的正则表达式不会匹配具有不同顺序属性的字体标签,例如
  • 属性没有以不同的顺序匹配,我很好。我使用的 HTML 编辑器控件只会按照我测试的顺序生成 标记。

标签: c# .net regex


【解决方案1】:

您的 IsMatch 方法使用选项 RegexOptions.IgnorePatternWhitespace,它允许您将 cmets 放入正则表达式中,因此您必须对 # 字符进行转义,否则它将被解释为注释。

if (!IsMatch(tagname,@"<font(\s*size=""\d{1}"")?
    (\s*color=""((\#[0-9a-f]{6})|(\#[0-9a-f]{3})|red|green|blue|black|white)"")?
    (\s*face=""(Arial|Courier New|Garamond|Georgia|Tahoma|Verdana)"")?
    \s?>"))
{
    html = html.Remove(tag.Index, tag.Length);
}

【讨论】:

    【解决方案2】:

    我看不出正则表达式有什么明显错误。我会尝试通过删除部分正则表达式来隔离问题,直到问题消失,然后专注于导致问题的部分。

    【讨论】:

    • 我不确定这与正则表达式有什么关系——它对我来说很好
    【解决方案3】:

    对我来说很好用...您使用的是什么版本的 .NET 框架,exact 异常是什么?

    另外 - 你的 IsMatch 方法是什么样的?这只是传递给Regex.IsMatch 的途径吗?

    [update] 问题是 OP 的示例代码没有显示他们正在使用 IgnorePatternWhitespace 正则表达式选项;使用此选项不起作用;没有这个选项(即如所示),代码很好。

    【讨论】:

      【解决方案4】:

      下载 Chris Sells Regex Designer。它是测试 .NET 正则表达式的绝佳免费工具。

      我不确定这个正则表达式是否会做你想要的,因为它取决于与你在正则表达式中的属性匹配的属性的顺序。例如,如果 face="Arial" 先于 size="5",则 face= 将不匹配。

      您的正则表达式中存在一些转义问题。您需要使用\ 转义您的" 您需要使用\ 转义您的# 您需要在Courier New 中使用\s 而不仅仅是空格。您需要使用RegexOptions.IgnorePatternWhitespaceRegexOptions.IgnoreCase options

      <font
      (\s+size=\"\d{1}\")?
      (\s+color=\"((\#[0-9a-f]{6})|(\#[0-9a-f]{3})|red|green|blue|black|white)\")?
      (\s+face=\"(Arial|Courier\sNew|Garamond|Georgia|Tahoma|Verdana)\")?
      

      # 字符是导致异常的原因,缺少一些误导性的 ) 消息。

      【讨论】:

      • 属性的顺序对我来说总是相同的,因为我正在使用文本编辑器控件。我不需要因为 @ 符号而逃避我的 "。这是 "courier new" 的一个很好的捕捉。我没有看到那个。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      相关资源
      最近更新 更多