需求:將文本中的 BBCode 顏色標籤 [black]text[/black]、[orange]text[/orange] 轉換為 HTML <span style="color:black">text</span>。要求標籤必須配對匹配,[black]hello[/orange] 不應被替換。
public class BbCodeParser {
// 預編譯正則,避免重複編譯開銷
private static final Map REPLACEMENTS = new LinkedHashMap<>();
static {
// 使用非貪婪匹配 .+? 確保最短匹配,捕獲組 $1 為內容
REPLACEMENTS.put(Pattern.compile("\\[black\\](.+?)\\[/black\\]"),
"$1");
REPLACEMENTS.put(Pattern.compile("\\[orange\\](.+?)\\[/orange\\]"),
"$1");
// 可擴展更多顏色
REPLACEMENTS.put(Pattern.compile("\\[red\\](.+?)\\[/red\\]"),
"$1");
REPLACEMENTS.put(Pattern.compile("\\[blue\\](.+?)\\[/blue\\]"),
"$1");
}
public static String parse(String text) {
if (TextUtils.isEmpty(text)) return "";
String result = text;
for (Map.Entry entry : REPLACEMENTS.entrySet()) {
Matcher matcher = entry.getKey().matcher(result);
result = matcher.replaceAll(entry.getValue());
}
return result;
}
}
| 部分 | 含義 |
|---|---|
\\[black\\] | 匹配字面量 [black],方括號需轉義 |
(.+?) | 捕獲組:非貪婪匹配任意字符 (至少一個),盡可能少匹配 |
\\[/black\\] | 匹配字面量 [/black],確保閉合標籤一致 |
$1 | 替換字符串中引用第一個捕獲組的內容 |
public static String parseAdvanced(String text) {
// 統一正則匹配所有顏色標籤
Pattern pattern = Pattern.compile("\\[(black|orange|red|blue)\\](.+?)\\[/\\1\\]");
Matcher matcher = pattern.matcher(text);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
String color = matcher.group(1);
String content = matcher.group(2);
String replacement = "" + content + "";
matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
}
matcher.appendTail(sb);
return sb.toString();
}
String input = "Hello [black]World[/black], this is [orange]Orange[/orange] text.";
String output = BbCodeParser.parse(input);
// 結果: "Hello World, this is Orange text."
// 錯誤嵌套不匹配
String invalid = "[black]hello[/orange]";
String result = BbCodeParser.parse(invalid);
// 結果: "[black]hello[/orange]" (原樣保留,不匹配)
// 內容需 HTML 轉義,防止注入腳本
import android.text.Html;
String safeContent = Html.escapeHtml(content); // API 16+
// 或
String safeContent = content.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """);
// 替換時使用安全內容
String replacement = "" + safeContent + "";
commonmark-java、flexmark-java,標準化、擴展性強。Jsoup.clean(html, Whitelist.basic()),安全渲染富文本。核心原則:正則預編譯、非貪婪匹配、捕獲組替換、內容轉義防 XSS。BBCode 解析是正則實戰的經典入門場景。