在 HTML 中搜索和替换单词

2022-08-30 19:18:06

我试图做的是做一个“行话破坏者”。基本上,我在数据库中有一些html和一些词汇表术语。当这个人点击行话破坏者时,它会用一个漂亮的工具提示(wztooltip)替换文本中的单词,向他们展示他们的含义。

我一直在努力解决这个问题 正则表达式 / DOMDocument - 匹配和替换不在链接中的文本

答案似乎在于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();

答案 1

使用倒置单词字符选择正则表达式模式中除数字和字母以外的任何字符。由于这在文本 blob 的边界处仍会失败,因此还需要测试这些条件。因此,使用单词“term”作为您要搜索的文本:\W

(^term$)|(^term\W)|(\Wterm\W)|(\Wterm$)

第一个条件进行检查以确保该术语不是 Blob 的唯一内容,第二个条件检查它是否是第一个单词,第三个条件检查它是否包含在 blob 中,最后一个条件检查它是否是最后一个单词。

如果要将任何其他字符视为单词字符(例如连字符),则需要使用 重新格式化 。\W[^\w\-]

希望这有帮助。可能也可以执行优化,但这至少应该是一个很好的起点。


答案 2

假设所有词汇表的“单词”都由标准的“单词”字符组成(即),那么可以在正则表达式模式中的单词之前和之后放置一个简单的单词边界断言。尝试将相关语句替换为以下内容:[A-Za-z0-9_]

$element->innertext = preg_replace(
    '/\b'. $glossary_word .'\b/i',
    '<a '. $glossary_tip .' >'. $glossary['word'] .'</a>',
    $element->innertext);

这假设它已经运行到槽中(您的代码确实如此)。$glossary_wordpreg_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";