用PHP替换带标记链接的单词

时间:2010-08-18 00:16:34

标签: php regex cakephp tags

我有一个文本($text)和一个单词数组($tags)。文本中的这些单词应该替换为指向其他页面的链接,这样它们就不会破坏文本中的现有链接。在CakePHP中,TextHelper中有一个方法可以执行此操作,但它已损坏,并且会破坏文本中现有的HTML链接。该方法假设像这样工作:

$text=Text->highlight($text,$tags,'<a href="/tags/\1">\1</a>',1);

下面是CakePHP TextHelper中的现有代码:

function highlight($text, $phrase, $highlighter = '<span class="highlight">\1</span>', $considerHtml = false) {
  if (empty($phrase)) {
    return $text;
  }

  if (is_array($phrase)) {
    $replace = array();
    $with = array();

    foreach ($phrase as $key => $value) {
      $key = $value;
      $value = $highlighter;
      $key = '(' . $key . ')';
      if ($considerHtml) {
        $key = '(?![^<]+>)' . $key . '(?![^<]+>)';
      }
      $replace[] = '|' . $key . '|ix';
      $with[] = empty($value) ? $highlighter : $value;
    }
    return preg_replace($replace, $with, $text);
  } else {
    $phrase = '(' . $phrase . ')';
    if ($considerHtml) {
      $phrase = '(?![^<]+>)' . $phrase . '(?![^<]+>)';
    }

    return preg_replace('|'.$phrase.'|i', $highlighter, $text);
  }
}

4 个答案:

答案 0 :(得分:2)

您可以在此处查看(并运行)此算法:

http://www.exorithm.com/algorithm/view/highlight

通过一些变化可以使它变得更好更简单,但它仍然不完美。虽然效率较低,但我推荐Ben Doom的解决方案之一。

答案 1 :(得分:1)

替换HTML中的文本与替换纯文本根本不同。要确定文本是否是HTML标记的一部分,您需要查找所有标记以便不考虑它们。正则表达式并不是真正的工具。

我会尝试以下解决方案之一:

  • 找到所有单词的位置。从最后到第一个工作,确定每个是否是标记的一部分。如果没有,请添加锚点。
  • 将字符串拆分为块。每个块都是标签或纯文本。在纯文本块上运行替换,然后重新组装。

我认为第一个可能更有效率,但更容易出现程序员错误,所以我会留给你。

如果您想知道我为什么不直接解决此问题,请查看网站上有关正则表达式和HTML的所有问题,以及正则表达式不是解析器的方法。

答案 2 :(得分:0)

这段代码很好用。您可能需要做的是检查<span class="highlight">的CSS,并确保它设置为某种颜色,以便您区分它是高亮的。

.highlight { background-color: #FFE900; }

答案 3 :(得分:0)

非晶 - 我注意到格特编辑了你的帖子。您发布的两个代码片段是否完全

所以尽管原始代码是为突出显示而设计的,但我知道你正试图将其重新用于生成链接 - 它应该,并且确实可以正常工作(测试为已发布)。

HOWEVER 在第一个代码片段中转义可能是一个问题。

$text=Text->highlight($text,$tags,'<a href="/tags/\1">\1</a>',1);

工作得很好......但是如果你使用说话标记而不是引号,则反斜杠会作为逃避标记消失 - 你需要逃避它们。如果你不这样做,你会得到%01链接。

说明标记的正确方法是:

$text=Text->highlight($text,$tags,"<a href=\"/tags/\\1\">\\1</a>",1);

(注意使用\ 1而不是\ 1)