Search code examples
javaregexreplaceall

Java replaceAll with regex only replacing first instance


I am trying to update all url's in a CSS string and my regex only seems to get the first one. I want to get anything like:

url("file")
url('file');
url(file);

I also want to exclude things where the url is data:

url("data: ...");
url('data: ...');
url(data: ...);

I wrote some code to do this, but it only replaces the first one:

String str = ".ff0{font-family:sans-serif;visibility:hidden;}@font-face{font-family:ff1;src:url(f1.woff)format(\"woff\");}.ff1{font-family:ff1;line-height:1.330566;font-style:normal;font-weight:normal;visibility:visible;}@font-face{font-family:ff2;src:url(f2.woff)format(\"woff\");}.ff2{font-family:ff2;line-height:1.313477;font-style:normal;font-weight:normal;visibility:visible;}@font-face{font-family:ff3;src:url(f3.woff)format(\"woff\");}.ff3{font-family:ff3;line-height:1.386719;font-style:normal;font-weight:normal;visibility:visible;}@font-face{font-family:ff4;src:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1IiBoZWlnaHQ9IjUiPgo8cmVjdCB3aWR0aD0iNSIgaGVpZ2h0PSI1IiBmaWxsPSIjOWU5ZTllIj48L3JlY3Q+CjxwYXRoIGQ9Ik0wIDVMNSAwWk02IDRMNCA2Wk0tMSAxTDEgLTFaIiBzdHJva2U9IiM4ODgiIHN0cm9rZS13aWR0aD0iMSI+PC9wYXRoPgo8L3N2Zz4=)format(\"woff\");";
str = str.replaceAll("url\\((['\"]?)(?!data)(.*)\\1\\)","url(someURL/$2)");
out.println(str);

Any ideas on how to fix? I imagine it has something to do with the regex.


Solution

  • You probably want to use non-greedy quantifier (*? instead of *).

    To exclude the data entries properly, also use possessive quantifier for capturing the qoutes: ?+ instead of ?.

    So your regex should look as follows: url\((['"]?+)(?!data)(.*?)\1\) Note that you should probably escape some characters with extra slash as you did in your example.