[英]Automatically convert keywords to links in php
我正在尝试将存储在数组中的文本中的特定关键字转换为链接。
示例文字:
$text='This text contains many keywords, but also formated <a href="#keywords" title="keywords">keywords</a>.'
因此,现在我想将单词关键字转换为<a href="#keywords" title="keywords">#keywords</a>
。
我使用了非常简单的preg_replace函数
preg_replace('/keywords/i',' <a href="#keywords">keywords</a> ',$text);
但显然它将转换为链接,也将已经格式化为链接的字符串转换为链接,因此我得到了一个凌乱的html,例如:
$text='This text contains many <a href="#keywords" title="keywords">keywords</a>, but also formated <a href="#<a href="#keywords" title="keywords">keywords</a>" title="<a href="#keywords" title="keywords">keywords</a>"><a href="#keywords" title="keywords">keywords</a></a>.'
预期结果:
$text='This text contains many <a href="#keywords" title="keywords">keywords</a>, but also formated <a href="#keywords" title="keywords">keywords</a>.'
有什么建议么? 谢谢
编辑
我们距离完善的功能仅一步之遥,但在这种情况下仍然无法正常工作:
$text='This text contains many keywords, but also formated
<a href="http://www.keywords.com/keywords" title="keywords">keywords</a>.'
在这种情况下,它也替换了href中的word keywords
,因此我们再次得到了像这样的混乱代码
<a href="http://www.<a href="http://www.keywords.com/keywords" title="keywords">keywords</a>.com/<a href="http://www.keywords.com/keywords" title="keywords">keywords</a>" title="keywords">keywords</a>
我对正则表达式不太满意,但也许这个可以用:
/[^#>"]keywords/i
我认为它将做的是忽略#keywords
, >keywords
和"keywords
所有实例,并找到其余的实例。
经过测试后,它看起来也将替换单词之前的空格,并且如果keywords
是字符串的开头,则该字符串将不起作用。 它还没有保留原始大写字母。 我已经测试了这一点,它对我来说非常合适:
$string = "Keywords and keywords, plus some more keywords with the original <a href=\\"#keywords\\" title=\\"keywords\\">keywords</a>."; $string = preg_replace("/(?<![#>\\"])keywords/i", "<a href=\\"#keywords\\">$0</a>", $string); echo $string;
前三个被替换,保留原始大小写,最后一个保持不变。 这使用负向后看和反向引用 。
OP编辑的问题。 使用提供的新示例,以下正则表达式将起作用:
$string = 'This text contains many keywords, but also formated <a href="http://www.keywords.com/keywords" title="keywords">keywords</a>.'; $string = preg_replace("/(?<![#>\\".\\/])keywords/i", "<a href=\\"http://www.keywords.com/keywords\\" title=\\"keywords\\">$0</a>", $string); echo $string; // outputs: This text contains many <a href="http://www.keywords.com/keywords" title="keywords">keywords</a>, but also formated <a href="http://www.keywords.com/keywords" title="keywords">keywords</a>.
这将替换的所有实例keywords
不是由前面#
, >
, "
, .
,或/
。
这是问题所在:
关键字可以在href,标题或链接文本中以及其中的任何位置(例如,关键字是sanity
而您已经具有href="insanity"
。甚至更糟的是,您可能拥有非关键字)恰好包含关键字的链接,例如:
<a href="http://example.org/">Click here to find more keywords and such!</a>
在上面的示例中,即使它符合所有其他可能的条件(最容易测试的条件之前和之后都有空格),它仍然会导致链接中的链接,我认为这会中断互联网。
因此,您需要使用lookaheads
和lookbehinds
来检查关键字是否包装在链接中。 但是有一个陷阱:后视必须具有定义的模式(意味着没有通配符)。
我以为自己会是英雄,并向您展示解决此问题的简便方法,因此可以达到以下目的:
'/(?<!\<a.?>)[list|of|keywords](?!\<\/a>)/'
除非您不能执行此操作,否则在本例中,后向具有该通配符。 没有它,您将最终获得超级贪婪的表情。
因此,我建议的替代方法是使用正则表达式查找所有链接元素,然后使用str_replace
用占位符替换掉它们,然后最后用占位符替换它们。
这是我的操作方式:
$text='This text contains many keywords, but also formated <a href="#keywords" title="keywords">keywords</a>.';
$keywords = array('text', 'formatted', 'keywords');
//This is just to make the regex easier
$keyword_list_pattern = '['. implode($keywords,"|") .']';
// First, get all matching keywords that are inside link elements
preg_match_all('/<a.*' . $keyword_list_pattern . '.*<\/a>/', $text, $links);
$links = array_unique($links[0]); // Cleaning up array for next step.
// Second, swap out all matches with a placeholder, and build restore array:
foreach($links as $count => $link) {
$link_key = "xxx_{$count}_xxx";
$restore_links[$link_key] = $link;
$text = str_replace($link, $link_key, $text);
}
// Third, we build a nice replacement array for the keywords:
foreach($keywords as $keyword) {
$keyword_links[$keyword] = "<a href='#$keyword'>$keyword</a>";
}
// Merge the restore links to the bottom of the keyword links for one mass replacement:
$keyword_links = array_merge($keyword_links, $restore_links);
$text = str_replace(array_keys($keyword_links), $keyword_links, $text);
echo $text;
您可以更改RegEx,使其仅定位在前面有空格的关键字。 由于格式化的关键字不包含空格。 这是一个例子。
$text = preg_replace('/ keywords/i',' <a href="#keywords">keywords</a>',$text);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.