我要做的就是做一个'行话破坏者'。 基本上我在数据库中有一些html和一些词汇表术语。 当这个人点击行话破坏者时,它会用一个漂亮的工具提示(wztooltip)替换文本中的单词,这些工具提示显示了它们的含义。
我一直在努力研究这个问题并且一直在密切关注这个问题 Regex / DOMDocument - match and replace text not in a link
似乎答案在于simple_html_dom库,但我无法让它工作。 显然,任何已经链接的单词都不会被触及。 这是我所得到的内容。
$html = str_get_html($article['content']);
$query_glossary = "SELECT word,glossary_term_id,info FROM glossary_terms WHERE status = 1 ORDER BY LENGTH(word) DESC";
$result_glossary = mysql_query_run($query_glossary);
while($glossary = mysql_fetch_array($result_glossary)) {
$glossary_link = SITEURL.'/glossary/term/'.string_to_url($glossary['word']).'-'.$glossary['glossary_term_id'];
if(strlen($glossary['info'])>400) {
$glossary_info = substr(strip_tags($glossary['info']),0,350).' ...<br /> <a href="'.$glossary_link.'">Read More</a>';
}
else {
$glossary_info = $glossary['info'];
}
$glossary_tip = 'href="javascript:;" onmouseout="UnTip();" class="article_jargon_highligher" onmouseover="'.tooltip_javascript('<a href="'.$glossary_link.'">'.$glossary['word'].'</a>',$glossary_info,400,1,0,1).'"';
$glossary_word = $glossary['word'];
$glossary_word = preg_quote($glossary_word,'/');
//once done we can replace the words with a nice tip
foreach ($html->find('text') as $element) {
if (!in_array($element->parent()->tag,array())) {
//problems are case aren't taken into account and grammer
$element->innertext = str_ireplace(''.$glossary['word'].' ',' <a '.$glossary_tip.' >'.$glossary['word'].'</a> ', $element->innertext);
//$element->innertext = str_ireplace(''.$glossary['word'].',',' <a '.$glossary_tip.'>'.$glossary['word'].'</a> ', $element->innertext);
//$element->innertext = preg_replace ("/\s(".$glossary_word.")\s/ise","nothing(' <a'.'$glossary_tip.'>'.'$1'.'</a> ')" , $element->innertext);
// $element->innertext = str_replace('__glossary_tip_replace__',$glossary_tip, $element->innertext);
}
}
}
$article['content'] = $html->save();
答案 0 :(得分:11)
使用倒置字符\W
选择正则表达式中除数字和字母以外的任何字符。因为这仍然会在文本blob的边界处失败,所以您还需要测试这些条件。因此,使用“term”一词作为您要搜索的文本:
(^term$)|(^term\W)|(\Wterm\W)|(\Wterm$)
第一个条件检查以确保该术语不是blob的唯一内容,第二个条件检查它是否是第一个单词,第三个是否包含在blob中,而最后一个如果是最后一个单词。< / p>
如果您想将任何其他字符视为单词字符(例如连字符),则需要使用\W
重新定位[^\w\-]
。
希望这会有所帮助。可能还可以进行优化,但这至少应该是一个很好的起点。
答案 1 :(得分:8)
假设您的所有词汇表“单词”都由标准的“单词”字符组成(即[A-Za-z0-9_]
),那么可以在正则表达式模式中的单词之前和之后放置一个简单的单词边界断言。尝试用以下方法替换pertinant语句:
$element->innertext = preg_replace(
'/\b'. $glossary_word .'\b/i',
'<a '. $glossary_tip .' >'. $glossary['word'] .'</a>',
$element->innertext);
这假定$glossary_word
已经通过preg_quote
(您的代码所做的)运行。
但是,如果词汇表单词可能包含其他非标准单词字符(例如'-'
短划线),则可以制定更复杂的正则表达式,其中包含前瞻和后瞻以确保只匹配整个单词。例如:
$re_pattern = "/ # Match a glossary whole word.
(?<=[\s'\"]|^) # Word preceded by whitespace, quote or BOS.
{$glossary_word} # Word to be matched.
(?=[\s'\".?!,;:]|$) # Word followed by ws, quote, punct or EOS.
/ix";
答案 2 :(得分:3)
我在JS中遇到个别单词的问题。我做的是以下(你可以将它从JS翻译成PHP):
它实际上对我很有用。 :)
var words = document.body.innerHTML;
// FIRST PASS
// remove scripts
words = words.replace(/<script[\s\S]*?>[\s\S]*?<\/script>/gi, '');
// remove CSS
words = words.replace(/<style[\s\S]*?>[\s\S]*?<\/style>/gi, '');
// remove comments
words = words.replace(/<!--[\s\S]*?-->/g, '');
// remove html character entities
words = words.replace(/&.*?;/g, ' ');
// remove all HTML
words = words.replace(/<[\s\S]*?>/g, '');
// SECOND PASS
// remove all newlines
words = words.replace(/\n/g, ' ');
// replace multiple spaces with 1 space
words = words.replace(/\s{2,}/g, ' ');
// split each word
words = words.split(/[^a-z-']+/gi);