首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# UBB 碼解析器實作:正則表達式轉換 HTML 的完整元件程式碼

     編輯:關於C語言

UBB 碼簡介

UBB (Universal Bulletin Board) 碼是論壇常用的輕量標記語言,以方括號標籤包裹內容(如 [b]粗體[/b]),最終轉換為 HTML 顯示。雖然現代富文本編輯器(如 FreeTextBox、CKEditor)已主流,但 UBB 解析器在舊系統維護、輕量評論系統、安全過濾場景仍有價值。

完整解析器實作

using System;
using System.Text;
using System.Text.RegularExpressions;

namespace TextProcessing {
    /// 
    /// UBB 碼轉 HTML 處理器
    /// 
    public static class UbbParser {
        public static string ToHtml(string input) {
            if (string.IsNullOrEmpty(input)) return string.Empty;
            
            var result = input;
            
            // 1. 空白字元處理
            result = result.Replace(" ", " ");
            
            // 2. HTML 編碼防 XSS
            result = result.Replace("<", "<").Replace(">", ">");
            
            // 3. 定義標籤轉換規則:Pattern → Replacement
            var rules = new (string Pattern, string Replacement)[] {
                // 基本樣式
                (@"(\[b\])([\s\S]*?)(\[/b\])", "<b>$2</b>"),
                (@"(\[i\])([\s\S]*?)(\[/i\])", "<i>$2</i>"),
                (@"(\[u\])([\s\S]*?)(\[/u\])", "<u>$2</u>"),
                
                // 字型屬性
                (@"(\[size=([1-7])\])([\s\S]*?)(\[/size\])", "<font size=\"$2\">$3</font>"),
                (@"(\[color=([^\]]+)\])([\s\S]*?)(\[/color\])", "<font color=\"$2\">$3</font>"),
                (@"(\[font=([^\]]+)\])([\s\S]*?)(\[/font\])", "<font face=\"$2\">$3</font>"),
                
                // 超連結
                (@"(\[url\])([\s\S]*?)(\[/url\])", "<a href=\"$2\" target=\"_blank\">$2</a>"),
                (@"(\[url=([^\]]+)\])([\s\S]*?)(\[/url\])", "<a href=\"$2\" target=\"_blank\">$3</a>"),
                
                // Email
                (@"(\[email\])([\s\S]*?)(\[/email\])", "<a href=\"mailto:$2\" target=\"_blank\">$2</a>"),
                (@"(\[email=([^\]]+)\])([\s\S]*?)(\[/email\])", "<a href=\"mailto:$2\" target=\"_blank\">$3</a>"),
                
                // 上下標
                (@"(\[sup\])([\s\S]*?)(\[/sup\])", "<sup>$2</sup>"),
                (@"(\[sub\])([\s\S]*?)(\[/sub\])", "<sub>$2</sub>"),
                
                // 對齊
                (@"(\[align=([^\]]+)\])([\s\S]*?)(\[/align\])", "<p align=\"$2\">$3</p>"),
                
                // 標題
                (@"(\[h=([1-6])\])([\s\S]*?)(\[/h\])", "<h$2>$3</h$2>"),
                
                // 圖片(特定系統整合)
                (@"\[picture\](\d+?)\[/picture\]", 
                    "<a href=\"ShowImage.aspx?Type=ALL&Action=forumImage&ImageID=$1\" target=\"_blank\">" +
                    "<img border=\"0\" title=\"點擊查看大圖\" src=\"ShowImage.aspx?Action=forumImage&ImageID=$1\" /></a>"),
                
                // 段落
                (@"((\r\n)*\[p\])([\s\S]*?)((\r\n)*\[/p\])", "<p class=\"pstyle\">$3</p>"),
            };
            
            // 套用所有簡單標籤規則
            foreach (var (pattern, replacement) in rules) {
                result = Regex.Replace(result, pattern, replacement, RegexOptions.IgnoreCase);
            }
            
            // 4. 列表處理(需特殊邏輯處理巢狀 * 項目)
            result = ProcessLists(result);
            
            // 5. 換行處理
            result = Regex.Replace(result, @"(\r\n)(( |\s)*)(?<text>\S)", "<br> ${text}");
            result = result.Replace("\r\n", "<br>");
            
            return result;
        }
        
        private static string ProcessLists(string input) {
            // 簡化版:處理 [list]...[*]item\r\n...[/list]
            var pattern = @"(\[list(=(A|a|I|i| ))?\])([\s\S]*?)(\[/list\])";
            return Regex.Replace(input, pattern, m => {
                var listType = m.Groups[3].Success ? m.Groups[3].Value : "disc";
                var content = m.Groups[4].Value;
                // 處理 [*] 項目
                content = Regex.Replace(content, @"\[\*\]([\s\S]*?)(\r\n|$)", "<li>$1</li>");
                return $"<ul type=\"{listType}\">{content}</ul>";
            }, RegexOptions.IgnoreCase | RegexOptions.Singleline);
        }
    }
}

使用範例

string ubb = @"
[b]重要公告[/b]
[color=red]系統將於今晚維護[/color]
[url=https://example.com]官方網站[/url]
[list]
[*]項目一
[*]項目二
[/list]
";

string html = UbbParser.ToHtml(ubb);
// 輸出對應 HTML

設計要點與擴充建議

  1. 處理順序:HTML 編碼 → 標籤轉換 → 換行,避免標籤內容被誤編碼
  2. 非貪婪匹配:[\s\S]*? 確保跨行匹配且不跨標籤
  3. 忽略大小寫:RegexOptions.IgnoreCase 兼容使用者輸入習慣
  4. XSS 防護:輸入先 HTML 編碼,再轉換標籤,確保使用者無法注入任意 HTML
  5. 效能優化:預編譯 Regex、合併規則、避免重複掃描
  6. 巢狀標籤:現實版需遞迴或狀態機處理 [b][i]text[/i][/b] 等巢狀結構
  7. 擴充性:規則表驅動設計,新增標籤只需加入陣列元素

現代替代方案

  • Markdown:更流行、標準化、生態豐富(Markdig、MarkdownSharp)
  • HTML Sanitizer:允許安全 HTML 子集(HtmlSanitizer 套件)
  • 富文本編輯器:CKEditor、TinyMCE、Quill 直接產出 HTML

UBB 解析器雖屬經典技術,但其規則驅動、正則轉換、安全優先的設計思維,對理解標記語言處理、建構自訂 DSL 解析器極具參考價值。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved