我很难看到一个简单的Regex任务。我想用以下排除项替换文本中具有大写字母和小写字母的所有href链接。
例如
href="/image-ZOOM.aspx?UPPERcasE=someThing"
匹配并替换为
href="/image-zoom.aspx?uppercase=something"
href="/image-coorect.aspx"
- 不匹配
此外,它会排除href="javascript:function();"
,并且不会在<% %>
代码之间小写任何内容。
例如:
href="/images/PDFs/<%=Product.ShortSku %>.pdf"
被翻译成
href="/images/**pdfs**/<%=Product.ShortSku %>.pdf"
我尝试了类似href="([^"]*[A-Z]+[^"]*)"
的内容,但仍然匹配全部小写的链接。你能不能发光一下。
谢谢!
答案 0 :(得分:6)
棘手的部分是您的<% ... %>
要求。一旦将URL的每个部分分成组,这实际上非常简单。
href="/images/PDFs/<%=Product.ShortSku %>.pdf"
|_____1_____||__________2_________||_3_|
通过理解上述内容,您最终会将其用于其他字符串:
href="/image-ZOOM.aspx?UPPERcasE=someThing"
|________________1_________________|
我最终得到了这种使用命名组的模式:
@"href=""(?!javascript:)(?=[^""]*[A-Z])(?<Start>[^""<]+)(?<Special><%[^""]+%>)?(?<End>[^""]*)"""
href=""
:匹配href并打开双引号。(?!javascript:)
:负面预测忽略javascript函数。(?=[^""]*[A-Z])
:正面预测在内容中找到大写字母。 [^""]*
匹配任何不是双引号的char。这样做是为了避免超出内容的末尾并贪婪地匹配非预期的内容。(?<Start>[^""<]+)
:与任何char匹配的命名组,只要它不是双引号或开括号括号。查看之前的描述 - 角括号检查确保在遇到<% ... %>
内容时停止。如果没有,模式将继续,直到遇到结束双引号。(?<Special><%[^""]+%>)?
:可选命名组,用于捕获<% ... %>
内容。尾随?
将整个组标记为可选。(?<End>[^""]*)
:命名组以匹配任何剩余内容。请注意,我使用*
使其匹配零个或多个内容。这允许模式的这一部分在特殊组不存在的情况下充当可选匹配。""
:关闭双引号。示例代码:
string[] inputs =
{
"href=\"/image-ZOOM.aspx?UPPERcasE=someThing\"", // match
"href=\"/image-coorect.aspx\"", // no match, lowercase
"href=\"javascript:function();\"", // no match, javascript
"href=\"/images/PDFs/<%=Product.ShortSku %>.pDf\"", // bypass <% %> content
};
string pattern = @"href=""(?!javascript:)(?=[^""]*[A-Z])(?<Start>[^""<]+)(?<Special><%[^""]+%>)?(?<End>[^""]*)""";
foreach (var input in inputs)
{
Console.WriteLine("{0,6}: {1}", Regex.IsMatch(input, pattern), input);
string result = Regex.Replace(input, pattern,
m => "href=\""
+ m.Groups["Start"].Value.ToLower()
+ m.Groups["Special"].Value
+ m.Groups["End"].Value.ToLower()
+ "\"");
Console.WriteLine("Result: " + result);
Console.WriteLine();
}
这使用lambda代替MatchEvaluator
。基本上我们正在重建字符串并引用命名组,改变我们想要修改的组的大小写。这段代码的一个微妙的关键是,如果一个组不匹配,我们仍然可以引用它,它只会给我们一个空字符串。此外,这可能在代码中并不明显,但是当匹配失败时,原始字符串将由Regex.Replace
不加改变地返回。
答案 1 :(得分:1)
也许您正在使用“/ i”修饰符,请确保您没有使用“RegexOptions.IgnoreCase”
List<string> list = new List<string>() {
"href=\"/image-ZOOM.aspx?UPPERcasE=someThing\"",
"href=\"/image-zoom.aspx?uppercase=something\"",
"href=\"/image-coorect.aspx\"",
"href=\"javascript:function();\""
};
foreach (string l in list)
{
if (Regex.IsMatch(l, "href=\"([^\"]*[A-Z]+[^\"]*)\""))
{
Console.WriteLine(l);
}
}
只匹配:href =“/ image-ZOOM.aspx?UPPERcasE = someThing”
答案 2 :(得分:1)
好的,我很困惑。如果页面上有一组控件和/或标签,则可以测试它们是否为锚类型,如果是,则可以从标签中获取href属性,然后将href设置为href.ToLower。
是否有特定的原因使用正则表达式来解决字符串和DOM解析问题?对我来说似乎有些过分。