我对使用preg_replace_callback()
我有一个$content
,里面有一些网址。
以前我用过
$content = preg_match_all( '/(http[s]?:[^\s]*)/i', $content, $links );
foreach ($links[1] as $link ) {
// we have the link. find image , download, replace the content with image
// echo '</br>LINK : '. $link;
$url = esc_url_raw( $link );
$url_name = parse_url($url);
$url_name = $description = $url_name['host'];// get rid of http://..
$url = 'http://somescriptonsite/v1/' . urlencode($url) . '?w=' . $width ;
}
return $url;
但我真正需要的是用我解析的URL替换原始URL ......
所以我尝试了preg_replace_callback:
function o99_simple_parse($content){
$content = preg_replace_callback( '/(http[s]?:[^\s]*)/i', 'o99_simple_callback', $content );
return $content;
}
和:
function o99_simple_callback($url){
// how to get the URL which is actually the match? and width ??
$url = esc_url_raw( $link );
$url_name = parse_url($url);
$url_name = $description = $url_name['host'];// get rid of http://..
$url = 'http://something' . urlencode($url) . '?w=' . $width ;
return $url; // what i really need to replace
}
我假设回调的工作方式是每个匹配都会调用回调(递归?)并返回结果,从而允许在$ content中使用已解析的{{1}即时替换URL中的URL来自$url
。
但是这里的另一个question(特别是this comment)引发了我的怀疑。
如果o99_simple_callbac()
实际上传递了整个匹配数组,那么我之前使用过的(第一个例子中为preg_replace_callback()
)和回调示例之间究竟有什么区别?
我错过了什么/误会?
使用解析后的网址替换preg_match_all()
中找到的URL的正确方法是什么?
答案 0 :(得分:4)
其他答案可能已经足够,但让我再用一个更简单的例子再给你一次。
假设我们在$subject
,
RECORD Male 1987-11-29 New York
RECORD Female 1987-07-13 Tennessee
RECORD Female 1990-04-14 New York
以及$pattern
中的以下正则表达式,
/RECORD (Male|Female) (\d\d\d\d)-(\d\d)-(\d\d) ([\w ]+)/
让我们比较三种方法。
首先,香草preg_match_all
:
preg_match_all($pattern, $subject, $matches);
以下是$matches
的结果:
Array
(
[0] => Array
(
[0] => RECORD Male 1987-11-29 New York
[1] => RECORD Female 1987-07-13 Tennessee
[2] => RECORD Female 1990-04-14 New York
)
[1] => Array
(
[0] => Male
[1] => Female
[2] => Female
)
[2] => Array
(
[0] => 1987
[1] => 1987
[2] => 1990
)
[3] => Array
(
[0] => 11
[1] => 07
[2] => 04
)
[4] => Array
(
[0] => 29
[1] => 13
[2] => 14
)
[5] => Array
(
[0] => New York
[1] => Tennessee
[2] => New York
)
)
我们是否在您的示例中使用您的示例中的URL字段讨论性别字段,很明显循环遍历$matches[1]
遍历只是该字段:
foreach ($matches[1] as $match)
{
$gender = $match;
// ...
}
但是,正如您所注意到的,您对$matches[1]
所做的更改,即使您通过引用迭代其子数组,也不会 反映在$subject
,即您无法通过preg_match_all
执行替换。
在我们跳到preg_replace_callback
之前,让我们看一下preg_match_all
常用的标记之一,PREG_SET_ORDER
。
preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER);
这会产生一些(看似)完全不同的东西!
Array
(
[0] => Array
(
[0] => RECORD Male 1987-11-29 New York
[1] => Male
[2] => 1987
[3] => 11
[4] => 29
[5] => New York
)
[1] => Array
(
[0] => RECORD Female 1987-07-13 Tennessee
[1] => Female
[2] => 1987
[3] => 07
[4] => 13
[5] => Tennessee
)
[2] => Array
(
[0] => RECORD Female 1990-04-14 New York
[1] => Female
[2] => 1990
[3] => 04
[4] => 14
[5] => New York
)
)
现在,每个子阵列包含每个匹配的捕获组的集,而不是匹配的集合,每个捕获组。 (换句话说,这是另一个数组的转置。)如果你想玩每场比赛的性别(或URL),你现在必须写这个:
foreach ($matches as $match)
{
$gender = $match[1];
// ...
}
这就是preg_replace_callback
的样子。它为每个匹配集(即,同时包括所有其捕获组)调用回调,就像使用PREG_SET_ORDER
标志一样。也就是说,与使用preg_replace_callback
的方式形成鲜明对比,
preg_replace_callback($pattern, $subject, 'my_callback');
function my_callback($matches)
{
$gender = $match[1];
// ...
return $gender;
}
到PREG_SET_ORDER
示例。请注意两个示例如何以完全相同的方式迭代匹配,唯一的区别是preg_replace_callback
使您有机会返回替换值。
答案 1 :(得分:3)
它不会传递所有匹配项,但会为每个匹配项调用回调函数。回调函数不会收到单个字符串参数,而是收到字符串列表。 $match[0]
是整个匹配,$match[1]
是第一个捕获组(第一个parens之间的正则表达式中有什么)。
这就是你的回调应该是这样的:
function o99_simple_callback($match){
$url = $match[1];
//$url = esc_url_raw( $link );
$url_name = parse_url($url);
$url_name = $description = $url_name['host'];// get rid of http://..
$url = 'http://something' . urlencode($url) . '?w=' . $width ;
return $url; // what i really need to replace
}
上的手册示例
答案 2 :(得分:2)