Preg_replace还是preg_replace_callback?

时间:2011-09-01 10:19:29

标签: php preg-replace preg-replace-callback

我在某些使用旧系统的网页上有链接,例如:

<a href='/app/?query=stuff_is_here'>This is a link</a>

他们需要转换为新系统,如:

<a href='/newapp/?q=stuff+is+here'>This is a link</a>

我可以使用preg_replace t0更改我需要的一些内容,但我还需要用+'替换查询中的下划线。我目前的代码是:

//$content is the page html
$content = preg_replace('#(href)="http://www.site.com/app/?query=([^:"]*)(?:")#','$1="http://www.site.com/newapp/?q=$2"',$content);

我想要做的是在$ 2变量上运行str_replace,所以我尝试使用preg_replace_callback,但永远无法让它工作。我该怎么办?

4 个答案:

答案 0 :(得分:3)

你必须传递一个有效的callback [docs]作为第二个参数:一个函数名,一个匿名函数等。

以下是一个例子:

function my_replace_callback($match) {
    $q = str_replace('_', '+', $match[2]);
    return $match[1] . '="http://www.site.com/newapp/?q=' . $q;
}
$content = preg_replace_callback('#(href)="http://www.site.com/app/?query=([^:"]*)(?:")#', 'my_replace_callback', $content);

或者使用PHP 5.3:

$content = preg_replace_callback('#(href)="http://www.site.com/app/?query=([^:"]*)(?:")#', function($match) {
    $q = str_replace('_', '+', $match[2]);
    return $match[1] . '="http://www.site.com/newapp/?q=' . $q;
}, $content);

您可能还想尝试使用HTML解析器而不是正则表达式:How do you parse and process HTML/XML in PHP?

答案 1 :(得分:3)

使用dom解析文档,搜索所有“a”标记然后替换可能是一种好方法。有人已发表评论帖子this link,向您展示正则表达式并不总是使用html的最佳方式。

Ayways这段代码应该有效:

<?php
$dom = new DOMDocument;
//html string contains your html
$dom->loadHTML($html);
?><ul><?
foreach( $dom->getElementsByTagName('a') as $node ) {
    //look for href attribute
    if( $node->hasAttribute( 'href' ) ) {
        $href = $node->getAttribute( 'href' );
        // change hrefs value
         $node->setAttribute( "href", preg_replace( "/\/app\/\?query=(.*)/", "/newapp/?q=\1", $href ) );
    }
}
//save new html
$newHTML = $dom->saveHTML(); 
?>

请注意,我使用preg_replace执行此操作,但可以使用str_ireplace或str_replace

完成此操作
$newHref = str_ireplace("/app/?query=", "/newapp/?q=", $href);

答案 2 :(得分:0)

或者您可以使用简单的preg_match()并收集匹配的字符串。然后将str_replace()应用于其中一个匹配项并将“+”替换为“_”。

$content = preg_match('#href="\/[^\/]\/\?query=([^:"]+)#', $matches)
$matches[2] = 'newapp';
$matches[4] = str_replace('_', '+', $matches[4]);
$result = implode('', $matches)

答案 3 :(得分:0)

将数组作为模式和替换传递给preg_replace

preg_replace(array('|/app/|', '_'), array('/newappp/', '+'), $content);