php正则表达式用链接标记替换“某些单词”,但应在链接标记内排除“某些单词”

时间:2012-12-15 06:27:34

标签: php regex

我将html内容存储在数据库表中。在那个html内容中我想用链接标签替换“SOME WORDS”。但如果“SOME WORDS”已经在链接标签中,我应该省略它们。

e.g。
内容

<p>Lorem ipsum dolor SOME WORDS, consectetur adipiscing elit. <a href="http://example.com">SOME WORDS</a> elementum pharetra velit at cursus. Quisque blandit, nibh at eleifend ullamcorper</p>

输出应为

<p>Lorem ipsum dolor <a href="http://someurl">SOME WORDS</a>, consectetur adipiscing elit. <a href="http://example.com">SOME WORDS</a> elementum pharetra velit at cursus. Quisque blandit, nibh at eleifend ullamcorper</p>

如您所见,它应该在替换时排除现有的链接文本。

非常感谢一些指导,以便进入正确的轨道。

4 个答案:

答案 0 :(得分:3)

这是使用DOMDocument而不是正则表达式解决问题的方法:

$contents = <<<EOS
<p>Lorem ipsum dolor SOME WORDS, consectetur adipiscing elit. <a href="http://example.com">SOME WORDS</a> elementum pharetra velit at cursus. Quisque blandit, nibh at eleifend ullamcorper</p>
EOS;

$doc = new DOMDocument;
libxml_use_internal_errors(true);
$doc->loadHTML($contents);
libxml_clear_errors();

$xp = new DOMXPath($doc);

// find all text nodes
foreach ($xp->query('//text()') as $node) {
        // make sure it's not inside an anchor
        if ($node->parentNode->nodeName !== 'a') {
                $node->nodeValue = str_replace(
                    'SOME WORDS', 
                    'SOME OTHER WORDS', 
                    $node->nodeValue
                );
        }
}
// DOMDocument creates a full document and puts your fragment inside a body tag
// So we enumerate the children and save their HTML representation
$body = $doc->getElementsByTagName('body')->item(0);
foreach ($body->childNodes as $node) {
        echo $doc->saveHTML($node);
}

答案 1 :(得分:1)

简单正则表达式只有在确切的短语和链接内部没有任何其他符号或单词时才有效。您可以通过计算在发生之前存在开始和结束链接标记的次数来迭代所有出现的SOME WORDS以查看它们是否在链接内。试试这段代码:

$str = '<p>Lorem ipsum dolor SOME WORDS, consectetur adipiscing elit. <a href="http://example.com">SOME WORDS</a> elementum pharetra velit at cursus. Quisque blandit, nibh at eleifend ullamcorper</p>';
echo 'Before:' . $str;
$str_lc = strtolower($str);
$phrase = 'SOME WORDS';
$link = '<a href="http://someurl">SOME WORDS</a>';
$offset = 0;
while($position = strpos($str, $phrase, $offset))
{
    if (substr_count($str_lc, "<a", 0, $position) <= substr_count($str_lc, "</a>", 0, $position)) {
        $str = substr_replace($str, $link, $position, strlen($phrase));
        $str_lc = strtolower($str);
        $offset = $position + strlen($link) - strlen($phrase);
    } else {
        $offset = $position + 1;
    }
}
echo 'After:' . $str;

答案 2 :(得分:1)

如果你有3行的空间,这将是一个安全的赌注:

$text=preg_replace('~<a(.*)(SOME WORDS)(.*)</a>~','<a$1PLACEHOLDER$3</a>',$text);
$text=preg_replace('~SOME WORDS~','REPLACEMENT WORDS',$text);
$text=preg_replace('~PLACEHOLDER~','SOME WORDS',$text);

它将使用PLACEHOLDER文本/标签/其他任何内容,因此您不会替换链接内容(如果有的话)。

答案 3 :(得分:0)

这应该可以解决问题。

如果SOME WORDS被标签包围,只需检查正则表达式

preg_replace('/[^>]SOME WORDS[^<]/','<a href="http://someurl">SOME WORDS</a>',$str);