2015-11-05 104 views
1

我忙於嘗試學習Drupal/PHP並遇到問題,我希望有人可以提供幫助。我已閱讀其他類似帖子,但嘗試解決方案尚未解決,因此提出了一個新問題。在字符串中匹配單詞並在發現匹配的情況下替換整個單詞

我正在嘗試改編一個現有的Drupal模塊(D7的wordfilter,dev發佈),它將用替代方案替換任何褻瀆實例。舉例來說,如果一個給定的字符串包含要替換的字符串'word',那麼我需要匹配整個單詞,而不僅僅是違規字符,所以

'措辭經理得到了措辭。字!'

需要成爲

'<deleted> <deleted> got <deleted>. <deleted>!' 

,而不是

'<deleted>ing <deleted>er got <deleted>ed. <deleted>!'. 

我到目前爲止的代碼有幾個問題。首先,它只取代完全匹配,而不是整個單詞。其次,我有一個分隔符和轉義字符的問題。我已標記我在哪裏認爲問題與**問題1和**問題2.如果我錯了,請讓我知道。

通過發行2拋出的錯誤是

Warning: preg_replace(): Unknown modifier '$' 

我認爲這是與某些字符不正確轉義做。我試圖用換行符來包裝$ pattern變量,所以它讀取

$text = preg_replace('/' . $pattern . '/', "\${1}" . $replacement . "\${2}", $text); 

但沒有運氣。正則表達式不匹配任何東西。這個問題可能與正則表達式本身有關,但我確定它是正確的。我正在使用的模式是

$pattern = '^(.*?(\B'word'\B)[^$]*)$'; 

但是'word'被包裝在preq_quote調用中。

所以你去了。對於你們所有人來說,可能存在一大堆問題來撕碎碎片。我相信你們都可以聞到血液:-)如果我需要重寫整個功能,那就這樣吧。如果這是一個快速解決方案,那麼更好。如果我錯過了任何東西,或者想要更多信息,請告訴我,我將編輯該問題以包含它。我會非常感謝任何幫助,就像我說的那樣,我將這種方法作爲學習練習,因此歡迎所有(建設性)批評。

/** 
* hook_filter process operation callback. 
*/ 
function wordfilter_filter_process($text) { 
    //dpm($text); 
    $text = ' ' . $text . ' '; 
    $list = _wordfilter_list(); 


    $utf8 = variable_get('wordfilter_use_utf8_flag', FALSE); 
    $case_sensitive = variable_get('wordfilter_process_case_sensitive', FALSE); 
    $default_replacement = variable_get('wordfilter_default_replacement', '[filtered word]'); 

    //dpm($list); 

    foreach ($list as $word) { 
    // Prevent mysterious empty value from blowing away the node title. 
    if (!empty($word->words)) { 
     $replacement = ($word->replacement) ? $word->replacement : $default_replacement; 

     if ($replacement == '<none>') { 
     $replacement = ''; 
     } 

     if ($word->standalone) { 
     $pattern = '/(\W)' . preg_quote($word->words, '/') . '(\W)/'; 
     } 
     else { //**issue 1 
     //$pattern = '/' . preg_quote($word->words, '/') . '/'; 
     $pattern = '^(.*?(\B' . preg_quote($word->words, '/') . '\B)[^$]*)$'; 
     } 

     if (!$case_sensitive) { 
     $pattern .= 'i'; 
     } 

     if ($utf8) { 
     $pattern .= 'u'; 
     } 

     $split_text = preg_split('/(<[^>]*>)/i', drupal_substr($text, 1, -1), -1, PREG_SPLIT_DELIM_CAPTURE); 
     $split_text = array_values(array_filter($split_text)); 

     if (count($split_text) > 1) { 
     $new_string = ''; 
     foreach ($split_text as $part) { 
      if (!preg_match('/^</', $part)) { 
      //dpm($part); 
      $new_string .= preg_replace($pattern, "\${1}" . $replacement . "\${2}", $part); 
      //$new_string .= preg_replace($pattern, $replacement, $part); 
      } 

      else { 
      $new_string .= $part; 
      } 
     } 
     } 

     else { //**issue 2 
     $text = preg_replace($pattern, "\${1}" . $replacement . "\${2}", $text); 
     //$text = preg_replace($pattern, $replacement, $text); 
     } 
    } 
    } 
    $text = drupal_substr($text, 1, -1); 

    return $text; 
} 
+0

的[ 「壞詞語」 過濾器]可能的複製(http://stackoverflow.com/questions/24515/bad-words-filter)欺騙標誌 –

+0

的目標應該是此http://計算器.com/questions/273516/how-do-you-implement -a-good-profanity-filter –

回答

1
\bword\w* 

您可以簡單地使用this.See演示。

https://regex101.com/r/lR1eC9/7

+0

我認爲你的正則表達式模式對我所擁有的是一個肯定的改進,所以謝謝你。但是,在最後的'else'語句中位置** issue 2處的未知修飾符仍然存在錯誤。 –