我需要使用不同的根相对URL替换根相对URL:
/Images/filename.jpg
应替换为:
/new/images-dir/filename.jpg
我开始使用PHP的str_replace
函数:
$newText = str_replace('/Images/', '/new/images-dir/', $text);
...但后来我意识到它正在替换我不想要替换的绝对网址:
http://sub.domain.com/something/Images/filename.jpg
#...is being replaced with...
http://sub.domain.com/something/new/images-dir/filename.jpg
然后我转而使用PHP的preg_replace
函数,这样我就可以使用正则表达式来有选择地只替换根相对URL而不是绝对URL。但是,我似乎无法弄清楚这样做的语法:
$text = 'There is a root relative URL here: <img src="/Images/filename.jpg">'
. 'and an absolute here: <img src="http://sub.domain.com/something/Images/filename.jpg">'
. 'and one not in quotes: /Images/filename.jpg';
$newText = preg_replace('#/Images/#', '/new/images-dir/', $text);
如何编写正则表达式以便忽略任何绝对URL并仅替换根相对URL?
答案 0 :(得分:2)
在进行三次编辑以得到正确的正则表达式后,我得出结论,我的第一个答案是最好的。 PHP's string functions比正则表达式更适合此任务:
使用str_replace():
function match($value)
{
// The second condition is probably unnecessary,
// unless your path argument is incorrectly formatted
if( ($value[0] != "/") || (stristr($value, "http:") != FALSE) )
{
return $value;
}
return str_replace("/Images/", "/new/images-dir/", $value);
}
str_replace()的优点是可读性。
如果读者不理解正则表达式,他们仍然可以清楚地看到匹配的条件:输入字符串必须以“/”开头,并且不得包含“http:”。
此外,搜索键和替换字符串都以纯文本清楚地表示。
使用preg_replace():
function match($value)
{
$pattern = "/^(\/((.+?)\/)*?)Images\//";
// Assuming value is a root-relative path, everything
// before "Images/" should be capured into back-reference 1;
// The replacement string re-inserts it before "new/images-dir/"
return preg_replace($pattern, "\\1new/images-dir/", $value);
}
正则表达式尝试匹配以下内容:
^
,((.+?)/)
。该组由一个或多个懒惰量化字符和另一个正斜杠组成。两个match()
函数在测试时的运行方式如下:
match("http://test/more/Images/file"); // Returns original argument
match("/test/more/Images/file"); // Returns with match replaced
答案 1 :(得分:1)
如您所示,根相对链接通常在引号内。因此,请在报价上进行匹配,然后将其重新置于替代品中。
$text = 'There is a root relative image here: <img src="/Images/filename.jpg">';
$newText = preg_replace('#"/Images/#', '"/new/images-dir/', $text);
<强>更新强>
如果您有两种不同的情况,请尝试两种不同的特定的替换,而不是尝试设计一个完美的。让我们知道其他案例是什么。
如果你需要匹配更多,那么你正在寻找一个“负面的lookbehind断言”,所以你要确保它与之前的“http:// blah”部分不匹配。 lookbehind的问题是它需要一个静态字符串匹配...它不能有可变长度。 http://www.php.net/manual/en/regexp.reference.assertions.php
这样的事情可能有用,如果你主要使用.net和.com链接的链接,而图像部分位于根目录:
$text = 'There is a root relative image here: <img src="/Images/filename.jpg">';
$newText = preg_replace('#(?<=.net|.com|.org|.cc)/Images/#', '/new/images-dir/', $text);
答案 2 :(得分:1)
根据PHP documentation on Lookbehind assertions:
Lookbehind断言以
(?<=
开头,用于肯定断言,(?<!
用于否定断言。
使用这种语法,我能够让它工作:
$text = preg_replace('#(?<!http\://sub.domain.com/something)/Images/#', '/new/images-dir/', $text);