4

I have a bunch of CSS containing image urls that I want to find/replace. The CSS often has more than one url per line, and the urls can vary pretty widely:

.class{display:inline;} .stuff{background:green url(/dir/subdir/dir.with.dots/image.png)} a{color:blue;} .more-stuff{background:url("../updir/newdir/file_image-new.jpg") no-repeat;}

I want to make each url into url(../images/<filename>.<ext>) without the rest of the path.

The closest I have come is

/url\s*\("?(?:.+\/)*(.*?)\.(png|gif|jpe?g)"?\)/url(../images/$1.$2)/g

but the (?:.+\/)* will select the CSS between image urls. If I add a ? to the end of that section, I end up only replacing the first directory level.

Can I do this without look(ahead|behind)s? I don't know if the regex engine supports them.

Other examples I see seem to have the convenience of predictable line termination, with only one url per line.

Michael
  • 8,362
  • 6
  • 61
  • 88
  • [*Parsing CSS*](http://www.w3.org/TR/CSS2/syndata.html#uri) with regex is a [*pain*](http://stackoverflow.com/a/21395083). Anyways, what language/tool are you using ? – HamZa Jan 30 '14 at 15:02
  • I've been testing with Notepad++ and reFiddle (for the highlighting), but will ultimately use sed or python. – Michael Jan 30 '14 at 15:06
  • I will try to do this in Python but I've got one more question: Does the extensions need to be matched dynamically or will you define them with say `(?:png|jpe?g|gif|custom\.extension)` ? – HamZa Jan 30 '14 at 15:14
  • @HamZa: I looked at the SO link. Yikes! I have done things like this (where finding `url([^)]+)` is easy, finding `url()` is hard) in C# using delegates, but that's not an option here. I can define the extensions. No need to find them. – Michael Jan 30 '14 at 15:16
  • 1
    I've got something to do, I will maybe come back later but meanwhile enjoy [this regex](http://regex101.com/r/bY4fQ9) – HamZa Jan 30 '14 at 15:21
  • I am a working on a similar problem of extracting image links from text, this regex has been working great for me : `'[\(\'\"]([^\(\'\"]*?\.(?:jpg|png|gif).*?)[\)\'\"]'`. It matches any image links that are enclosed by ', ", (, ) – gskema Jan 30 '14 at 16:03

2 Answers2

4

How about:

Find what: url\s*\("?/?(?:[^/]+/)*?([^/]+\.(?:png|gif|jpe?g))"?\)
Replace with: url(../images/$1)

Toto
  • 89,455
  • 62
  • 89
  • 125
2

I used Toto's excellent answer to my question for a year.

However, the use case has expanded somewhat to include other images (.svg), fonts (.eot, .woff), and people's CSS tricks (.eot#?iefix). After a while, I got sick of adding extra file types to the regex.

The regex below (borrowing heavily from Toto) should take care of any file extension, even with junk on the end:

url\s*\("?\/?(?:[^\/]+\/)*?([^\/]+?\.[^\"\'\)\/]+)"?\)
url(../images/$1)

Bonus

# If you want to exclude Base64 encoded data, put in a negative lookahead
url\s*\("?(?!data:)\/?(?:[^\/]+\/)*?([^\/]+?\.[^\"\'\)\/]+)"?\)
url(../images/$1)

# If your engine supports backreferences, you can match quotes
url\s*\(\*(['"]?)\/?(?:[^\/]+\/)*?([^\/]+?\.[^\/]+)\1\s*\)
url(../images/$2)
Community
  • 1
  • 1
Michael
  • 8,362
  • 6
  • 61
  • 88