Skip to main content
 首页 » 编程设计

C# 正则表达式查找和替换只有大写字符的链接并且不匹配排除项

2024年01月22日26小虾米

我很难处理看似简单的 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]+[^"]*)" 的东西但这仍然匹配所有小写字母的链接。你能发光吗?

谢谢!

请您参考如下方法:

棘手的部分是你的 <% ... %>要求。一旦您将 URL 的每个部分分成组,它实际上就非常简单。

href="/images/PDFs/<%=Product.ShortSku %>.pdf" 
      |_____1_____||__________2_________||_3_| 
  1. 这个组必须存在。
  2. 这个组是可选的。
  3. 如果第 2 组不存在,则第 3 组也不存在,在这种情况下,第 1 组匹配整个 href 内容。如果第 2 组存在,则第 3 组将是 href 内容的其余部分。

通过理解上面的内容,你最终得到了其他字符串:

href="/image-ZOOM.aspx?UPPERcasE=someThing" 
      |________________1_________________| 

我最终得到了这个使用命名组的模式:

@"href=""(?!javascript:)(?=[^""]*[A-Z])(?<Start>[^""<]+)(?<Special><%[^""]+%>)?(?<End>[^""]*)""" 
  • href="" : 匹配 href 和左双引号。
  • (?!javascript:) : 否定前瞻以忽略 javascript 函数。
  • (?=[^""]*[A-Z]) : 积极向前看,在即将到来的内容中找到大写字母。 [^""]*匹配任何不是双引号的字符。这样做是为了避免越过内容末尾并贪婪地匹配不需要的内容。
  • (?<Start>[^""<]+) : 匹配任何字符的命名组,只要它不是双引号或左尖括号。查看前面的描述 - 尖括号检查确保我们在 <% ... %> 时停止遇到内容。如果没有,该模式将继续,直到遇到结束双引号。
  • (?<Special><%[^""]+%>)? : optional 要捕获的命名组 <% ... %>内容。尾随 ?将整个组标记为可选。
  • (?<End>[^""]*) : 命名组以匹配任何剩余内容。注意这里我使用 *使其匹配零个或多个内容。在 Special 组不存在的情况下,这允许模式的这一部分充当可选匹配项。
  • "" : 结束双引号。

示例代码:

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 会原封不动地返回原始字符串。 .