我有以下代码:http://ideone.com/mFUaqG
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);
}
}
不幸的是,这段代码并没有达到我的预期,即用字符串替换来替换所有出现的正则表达式。我们本质上是用绝对 URL 替换 CSS 和 HTML 中的相对 URL。它似乎只是取代了第一次出现,给出
div#header { background-image: url('http://www.google.ca/images/header-background.jpg'); } div#header { background-image: url('images/header-background.jpg'); }
href="http://www.google.ca/wtfguys.css" href="wtfguys.css"
作为输出。有什么建议吗?
您正在使用尝试匹配单引号和双引号属性值的正则表达式。问题是,您可能会匹配截断的值,因为这两种模式都无法确保开头引号与结尾引号匹配。另外,值本身应该缺少该引用。
因此,将起始引号包装到捕获组中,使用反向引用作为结束分隔符,并添加反向引用作为调和贪婪标记中前瞻的替代方案。然后,修复替换模式,因为反向引用的顺序会改变。
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 演示
.*
是贪婪的。匹配器将 wtfguys.css" href="wtfguys.css
捕获为 $2
,而不是 wtfguys.css
。您可以使用 .*?
或 [^\"]*
代替,因为 URL 内部甚至没有转义引号。此问题的参考解释了几个选项(包括 Wiktor 提到的选项):http://www.rexegg.com/regex-quantifiers.html#greedytrap.