为什么java.util.regex.matcher不匹配此字符串中的所有实例?

时间:2016-04-15 20:10:26

标签: java regex matcher replaceall

我有以下代码:http://ideone.com/mFUaqG

C

不幸的是,这段代码没有达到我的预期,即用字符串替换替换所有出现的正则表达式。我们基本上用绝对URLS替换CSS和HTML中的相对URL。它似乎只取代了第一次出现,给出了

import java.util.regex.Matcher;
import java.util.regex.Pattern;

class RegexUtils
{
    private static final Pattern resourceURLCSS     = Pattern.compile("url\\([\'\"](((?!://).)*)[\'\"]\\)");
    private static final Pattern resourceURLHTML    = Pattern.compile("(href|src|url)=[\'\"](((?!://).)*)[\'\"]");

    public static String makeCSSURLsAbsolute(String input, String baseURL)
    {
        Matcher matcher     = resourceURLCSS.matcher(input);
        return matcher.replaceAll("url('"+baseURL+"$1')");
    }
    public static String makeHTMLURLsAbsolute(String input, String baseURL)
    {
        Matcher matcher     = resourceURLHTML.matcher(input);
        return matcher.replaceAll("$1=\""+baseURL+"$2\"");
    }

    public static void main(String[] args)
    {
        String fixed    = RegexUtils.makeCSSURLsAbsolute("div#header { background-image: url('images/header-background.jpg'); } div#header { background-image: url('images/header-background.jpg'); }", "http://www.google.ca/");
        System.out.println(fixed);

        fixed           = RegexUtils.makeHTMLURLsAbsolute("href=\"wtfguys.css\" href=\"wtfguys.css\"", "http://www.google.ca/");
        System.out.println(fixed);
    }
}

作为输出。有什么建议吗?

2 个答案:

答案 0 :(得分:1)

您正在使用试图匹配单引号和双引号属性值的正则表达式。问题是,您可以匹配截断值,因为这两个模式都不能确保开头报价与结束匹配。此外,该值本身应该缺少该引用。

因此,将开头报价包装到一个捕获组中,使用backrefrence作为结束分隔符,并添加backrefrence作为调查贪婪令牌中前瞻的替代方法。然后,修复替换模式,因为反向引用的顺序将会改变。

private static final Pattern resourceURLCSS     = Pattern.compile("url\\((['\"])((?:(?!://|\\1).)*)\\1\\)");
private static final Pattern resourceURLHTML    = Pattern.compile("(href|src|url)=(['\"])((?:(?!://|\\2).)*)\\2");

public static String makeCSSURLsAbsolute(String input, String baseURL)
{
    Matcher matcher     = resourceURLCSS.matcher(input);
    return matcher.replaceAll("url('"+baseURL+"$2')");
}
public static String makeHTMLURLsAbsolute(String input, String baseURL)
{
    Matcher matcher     = resourceURLHTML.matcher(input);
    return matcher.replaceAll("$1=\""+baseURL+"$3\"");
}

请参阅IDEONE demo

答案 1 :(得分:0)

.*贪婪。匹配器将wtfguys.css" href="wtfguys.css捕获为$2,而不是wtfguys.css。您可以使用.*?[^\"]*代替,因为网址内部甚至没有转义引号。此问题的参考解释了几个选项(包括Wiktor提到的选项):http://www.rexegg.com/regex-quantifiers.html#greedytrap