1

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.

5
  • str = str.replaceAll(/url\((['\"]?)(?!data)(.*)\\1\)/g,"url(someURL/$2)"); You need to set the global identifier... the /g Commented Oct 21, 2015 at 18:56
  • Aren't you thinking of javascript? When I do this in java, I get a load of errors. Commented Oct 21, 2015 at 19:00
  • Whoops... been in JS land all day, misread the title... Commented Oct 21, 2015 at 19:01
  • Try with reluctant quantifier. So instead of (.*) use (.*?) Commented Oct 21, 2015 at 19:02
  • 1
    str = str.replaceAll("url\\((['\"]?)(?!data)(.*?)\\1\\)", "url($1someURL/$2$1)"); Commented Oct 21, 2015 at 19:03

3 Answers 3

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

That works thanks. Just one issue that I need to solve is that when data is surrounded by single or double quotes, it passes the regex. How would I fix that?
For that you would want to use possessive quantifier for matching these quotes: ?+ instead of ?: url\((['"]?+)(?!data)(.*?)\1\)
2

Your .* is greedy. It's capturing to the end of the string. Use .*?, instead, which will force the engine to capture as few characters as possible.

str = str.replaceAll("url\\((['\"]?)(?!data)(.*?)\\1\\)","url(someURL/$2)");

4 Comments

Thanks. Any idea how to fix the issue where it would apply when data is surrounded by single or double quotes?
I'm not clear what exact issue you're trying to address. The regex above already captures a url that is within single or double quotes into the second capture group. Are you trying to retain quotes after the string replacement?
If you look above at the data urls I posted to exclude, this regex only excludes ones without single and double quotes. I want to make sure that it excludes all data urls.
Sorry. I missed that you wanted to exclude data above. Got it.
0

Something like this should work:

~\((?!.*data).+\)~

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.