为啥在这个正则表达式中左括号被转义?
Posted
技术标签:
【中文标题】为啥在这个正则表达式中左括号被转义?【英文标题】: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="\d1")?(\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=""\d1"")?
(\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="\d1")?(\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=""\d1"")?
(\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 编辑器控件只会按照我测试的顺序生成 标记。 【参考方案1】:您的 IsMatch 方法使用选项 RegexOptions.IgnorePatternWhitespace
,它允许您将 cmets 放入正则表达式中,因此您必须对 # 字符进行转义,否则它将被解释为注释。
if (!IsMatch(tagname,@"<font(\s*size=""\d1"")?
(\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.IgnorePatternWhitespace
和RegexOptions.IgnoreCase options
。
<font
(\s+size=\"\d1\")?
(\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" 的一个很好的捕捉。我没有看到那个。以上是关于为啥在这个正则表达式中左括号被转义?的主要内容,如果未能解决你的问题,请参考以下文章