简体   繁体   中英

How can I make these relative URLs absolute using regular expressions?

I need to process CSS files to make any relative paths (using url()) absolute. It should match URIs in single or double quotes, or without quotes. The replacement should not be quoted.

Eg

url(/foo/bar.png) --> url(/foo/bar.png) [unchanged]
url(foo/bar.png) --> url(/path/to/file/foo/bar.png) [made absolute]
url("foo/bar.png") --> url(/path/to/file/foo/bar.png) [made absolute, no quotes]
url('foo/bar.png') --> url(/path/to/file/foo/bar.png) [made absolute, no quotes]

I tried many different patterns, including a lookahead for / and many variations of the below.

$dir = dirname($path);
$r = preg_replace('#url\(("|\')?([^/"\']{1}.+)("|\')?\)#', "url(/$dir/$2)", $contents);

Can't seem to get it right. Any help?

我想应该这样做:

$r = preg_replace('#url\(("|\'|)([^/"\'\)][^"\'\)]*)("|\'|)\)#', 'url(/'.$dir.'/$2)', $contents);

You could simplify two things. First for matching quotes, you should use ["']? rather than a group. And for detecting a relative path name, check for the presence of a letter rather than the absence of a slash.

preg_replace('#url\(  [\'"]?  (\w[^)"\']+)  [\'"]?  \)#x'

I'm using ) to detect the end of the braces rather than .+ . Though it would be more robust to list only allowed characters like [\\w/.]+

How about the following:

$pattern = '#url\([\'"]?(\w[\w\./]+)[\'"]?\)#i';

$subjects = array(
  'url(/foo/bar.png)',
  'url(foo/bar.png)',
  'url("foo/bar.png")',
  'url(\'foo/bar.png\')',
);

foreach ($subjects as $subject) {
  echo "$subject => ", preg_replace($pattern, "url(/path/to/$1)", $subject), "\n";
}

Outputs the following:

url(/foo/bar.png) => url(/foo/bar.png)
url(foo/bar.png) => url(/path/to/foo/bar.png)
url("foo/bar.png") => url(/path/to/foo/bar.png)
url('foo/bar.png') => url(/path/to/foo/bar.png)
$dir = dirname($path);
$r = preg_replace('#url\(([\'"]?)([^/].*?)\1\)#', "url(/{$dir}/$2)", $contents);
  • match url
  • match open paren
  • open capture group 1
  • match ' or " zero or once
  • close capturing group 1
  • open capturing group 2
  • match one character that is not a /
  • match zero or more characters ungreedily
  • close capturing group 2
  • match whatever was captured in capturing group 1 (this ensures a same-quote match, and works if there is no quote captured by 1)
  • match a close paren

Capturing group 2 contains the target data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM