我試圖在我正在開發的某個網站中完成搜索功能。由於我的搜索結果僅顯示匹配項目內容的摘錄,因此我想要做的是在搜索結果中突出顯示搜索字詞,並僅顯示實際包含這些搜索字詞的部分文字。放棄所有字符,但搜索字詞前後的前10個字
我想我會做的是從數據庫中獲取的全部內容,並使用preg_replace
插入四處搜尋範圍,並在同一時間提取之前僅在第10個單詞和術語後<span>
元素。因此,這是它的正則表達式的一部分:
(?:.*?)((?:\w+\W+){0,10})('.implode('|', $terms).')((?:\W*\w+\W+){0,10})
基本上,我嘗試使用非捕獲子模式「丟棄」,除了搜索詞前的前10個單詞的所有文字,然後前拿到10個字術語本身,然後是接下來的10個單詞。
這是preg_replace
替換文本:
\\1<span class="search-term search-term-content">\\2</span>\\3...
搜索條件正在通過MySQL
的MATCH()...AGAINST()
爲MyISAM FULLTEXT
多個列的indeces搜索。但是,上述正則表達式只能應用於一列(我們稱之爲使用上述正則表達式的列,content
)。
所以我的問題是每當我在其他列匹配但不在content
列上時,上面的正則表達式將從content
列中刪除所有文本。這是因爲(?:.*?)
子模式在一開始就會繼續匹配而不會發現下一個子模式。
我想知道是否有任何其他方式來實現沒有這種副作用的正則表達式的原始目的。我目前正在考慮簡單地使用preg_match_all
來匹配搜索詞和前後10個詞。我只是遍歷所有匹配並手動構建預覽文本。是的,這是一個很好的解決方案,但鑑於我對正則表達式的經驗不足,我認爲我不妨嘗試找到解決方案。
UPDATE
我只注意到我只得到空白contents
當我把2個或更多搜索項。除此之外,它完美的作品。我現在不知道爲什麼會發生這種情況。
更新2
Echo'ing preg_last_error()
,我得到這個錯誤PREG_BACKTRACK_LIMIT_ERROR
。我使用搜索字詞new
和post
。
正則表達式的var_dump
和條款顯示此:
@(?:.*?)((?:\w+\W+){0,10})(new|post)((?:\W*\w+\W+){0,10})@i
array
0 => string 'new' (length=3)
1 => string 'post' (length=4)
更新3
我以前Regex Coach
走我走過的匹配模式,它似乎回溯後太多找不到(new|post)
。目標文本只是一段隨機的3段文字。我想我需要爲這個任務找到更好的正則表達式。
UPDATE 4
使用Once-Only
子模式解決了這個問題。雖然我不知道它的細節,但我只是重新閱讀PHP手冊並閱讀其中的一部分,子模式有助於回溯太多。這是新的正則表達式:
(?:.*?)((?>\w+\W+){0,10})('.implode('|', $terms).')((?:\W*\w+\W+){0,10})
但我仍然樂於提供更好的正則表達式的建議。謝謝!
當一個搜索詞出現在另一個搜索詞的10個詞以內時,怎麼辦?通過這種方法,你將不會包括接下來的10個單詞。可以嗎?什麼時候搜索詞真的很頻繁?你可以回覆整個文本嗎?似乎你可能需要稍微昂貴的方法來做到這一點...... – Braiba 2012-07-18 07:35:19
preg_replace是否返回空字符串或null?如果它返回null,那麼在你的模式中有一個錯誤,在這種情況下,你可能想要回應一下。首先想到的是,您需要preg_quote這些值,除非您已經將它們分解爲字母數字字符只在構建數組的過程中。 – Braiba 2012-07-18 08:00:10
嗨!我更新了問題以指出錯誤。我同意搜索條件彼此太接近是一個問題。感謝您的評論!我不介意它在返回之前截斷內容,因而返回了整個文本。 – 2012-07-18 08:20:41