C#正则表达式仅使用大写字符查找和替换链接,并且不匹配排除项

时间:2010-11-18 20:04:15

标签: c# regex

我很难看到一个简单的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]+[^"]*)"的内容,但仍然匹配全部小写的链接。你能不能发光一下。

谢谢!

3 个答案:

答案 0 :(得分:6)

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

href="/images/PDFs/<%=Product.ShortSku %>.pdf"
      |_____1_____||__________2_________||_3_|
  1. 此组必须存在。
  2. 此论坛是可选的。
  3. 如果组2不存在,那么组3将不存在,在这种情况下组1匹配整个href内容。如果组2存在,则组3将是href内容的剩余部分。
  4. 通过理解上述内容,您最终会将其用于其他字符串:

    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解析问题?对我来说似乎有些过分。