3

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

<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

4 回答 4

3

用 dom 解析文档,搜索所有“a”标签然后替换可能是一个好方法。有人已经评论过向您发布此链接,以向您展示正则表达式并不总是使用 html 的最佳方式。

无论如何,这段代码应该可以工作:

<?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);
于 2011-09-01T10:41:57.110 回答
3

您必须传递一个有效的回调[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 解析器而不是正则表达式:您如何在 PHP 中解析和处理 HTML/XML?

于 2011-09-01T10:25:04.873 回答
0

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

$content = preg_match('#href="\/[^\/]\/\?query=([^:"]+)#', $matches)
$matches[2] = 'newapp';
$matches[4] = str_replace('_', '+', $matches[4]);
$result = implode('', $matches)
于 2011-09-01T10:33:55.177 回答
0

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

preg_replace(array('|/app/|', '_'), array('/newappp/', '+'), $content);
于 2011-09-01T10:52:34.213 回答