在文字內容中搜尋多個關鍵字並高亮顯示,是常見需求(如關鍵字廣告、文件檢索、論壇搜尋)。本文示範使用 Regex.Replace 搭配 MatchEvaluator 委派,實現不區分大小寫、多關鍵字一次替換為 <span class="highlight"> 標籤。
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Text.RegularExpressions" %>
<!DOCTYPE html>
<html>
<head>
<title>多關鍵字高亮搜尋</title>
<style>
.highlight { text-decoration:none; font-weight:bold; color:white; background:blue; padding:0 2px; border-radius:3px; }
</style>
</head>
<body>
<form id="form1" runat="server">
<h3>多關鍵字高亮搜尋示範</h3>
<asp:TextBox ID="txtKeywords" runat="server" Width="300px" />
<asp:Button ID="btnSearch" runat="server" Text="搜尋" OnClick="btnSearch_Click" />
<br />
<asp:Label ID="lblContent" runat="server" />
</form>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
lblContent.Text = @"Give the proper respect to hand-coding. You should both respect and loathe handwritten code.
You should respect it because there are often special cases integrated into code that are overlooked with a cursory inspection.
When replacing code you've written by hand, you need to make sure you have the special cases accounted for.
You should loathe hand-code because engineering time is extremely valuable, and to waste it on repetitive tasks is nearly criminal.
The goal of your generator should always be to optimize the organization's most valuable assets: the creativity and enthusiasm of the engineering team.";
}
}
protected void btnSearch_Click(object sender, EventArgs e)
{
string keywords = txtKeywords.Text.Trim();
if (!string.IsNullOrEmpty(keywords))
{
lblContent.Text = HighlightKeywords(keywords, lblContent.Text);
}
}
///
/// 將關鍵字以 | 分隔建立 Regex 替換模式
///
public string HighlightKeywords(string keywordInput, string inputText)
{
if (string.IsNullOrWhiteSpace(keywordInput) || string.IsNullOrEmpty(inputText))
return inputText;
// 關鍵字以空白分隔,轉義特殊字元後用 | 串聯
string pattern = string.Join("|", keywordInput.Split(new[] { ' ', ' ', ',', ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(k => Regex.Escape(k)));
if (string.IsNullOrEmpty(pattern)) return inputText;
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
return regex.Replace(inputText, m => $@"{m.Value}");
}
</script>
</body>
</html>
Split 後 Regex.Escape 轉義特殊字元(如 .、*、?),再用 | 串聯成 keyword1|keyword2|keyword3 模式。<span class="highlight"> 的字串,保留原始大小寫。\\b(keyword1|keyword2)\\b,避免「中」匹配到「中國」。+(AND)、-(NOT)、" "(精確片語)。inputText 執行 HttpUtility.HtmlEncode,再替換關鍵字,避免使用者輸入腳本。mark.js 或 highlight.js 於瀏覽器端處理,減輕伺服器負擔。| 問題 | 原因 | 解決 |
|---|---|---|
| HTML 標籤被破壞 | Regex 直接匹配原始 HTML 字串 | 僅對純文字節點處理,或使用 HtmlAgilityPack 解析 DOM 後替換文字節點 |
| 關鍵字含特殊字元報錯 | 未 Regex.Escape | 所有關鍵字必經 Regex.Escape |
| 效能差 | 大文字長度 × 關鍵字數 × 請求數 | 快取編譯後 Regex、改用全文搜尋引擎、移至客戶端 |
Regex + MatchEvaluator 是實現多關鍵字高亮的輕量方案,適合中小型文字處理。生產環境請注意 HTML 結構保護與 XSS 防禦,大規模應用請改用專業搜尋引擎。