
本文详解如何使用正则表达式精准匹配并清除 OpenAI API 返回文本中由 包裹的代码块标记(包括语言标识符和结尾的闭合符号),避免残留、跨行失效或误删问题,并提供健壮、可复用的 JavaScript 实现方案。
本文详解如何使用正则表达式精准匹配并清除 OpenAI API 返回文本中由 “` 包裹的代码块标记(包括语言标识符和结尾的闭合符号),避免残留、跨行失效或误删问题,并提供健壮、可复用的 JavaScript 实现方案。
在基于 OpenAI API 构建的前端聊天应用中,模型常以 Markdown 风格返回带语法高亮的代码片段,例如:
nav {background-color: #333;} nav ul {list-style-type: none; margin: 0; padding: 0;}
这类响应通常包含开头的 ““language(如 css)和结尾独立成行的。若仅用简单字符串替换(如 .replace(““`”, “”))或不完整的正则匹配,极易导致:
- 仅替换首个 “`,末尾闭合标记被遗漏;
- 语言标识符后内容未正确捕获,造成代码截断;
- 跨行内容因 . 默认不匹配换行符而失效;
- 多个代码块时处理不彻底。
✅ 正确解法是 单次正则全局匹配整个代码块结构,而非分步替换。推荐使用以下正则模式:
const codeBlockRegex = /```[a-z]*n([sS]*?)n```/gi; // 应用示例 fetch(API_URL, requestOptions) .then(res => res.json()) .then(data => { let content = data.choices[0].message.content.trim(); // 一步移除所有完整代码块(含语言声明与首尾 ```),保留内部代码 content = content.replace(codeBlockRegex, (_, innerCode) => innerCode.trim()); // 可选:进一步清理可能残留的孤立 ```(兜底)content = content.replace(/^```[sS]*?```$/gm, '').trim(); messageElement.textContent = content;}) .catch(() => { messageElement.classList.add("error"); messageElement.textContent = "Oops! Something went wrong. Please try again."; }) .finally(() => chatbox.scrollTo(0, chatbox.scrollHeight));
? 关键说明:
- /“`[a-z]*n([sS]*?)n“`/gi 中:
- [a-z]* 匹配可选的语言标识(如 html、javascript,忽略大小写 i 标志);
- n 显式匹配换行符,确保结构准确;
- [sS]*? 替代 .*?,真正匹配任意字符(含换行),实现跨行捕获;
- 捕获组 ($1) 提取纯代码内容,再通过回调函数 .replace(…, (_, innerCode) => innerCode.trim()) 安全注入;
- g 标志保证匹配多个代码块;i 支持 JavaScript 或 javascript 等变体。
⚠️ 注意事项:
- 若需保留代码块渲染(如配合 <pre><code> 高亮),不应删除 “`,而应解析后封装为 HTML 结构;本文聚焦「纯文本清洗」场景。
- 避免使用 replace(/“`/g, ”) 这类无上下文的暴力替换——它会误删代码内容中的反引号(如 CSS 字符串 content: ““`”;)。
- 生产环境建议增加空值与格式校验:if (!content || typeof content !== ‘string’) return;。
总结:处理 OpenAI 的 Markdown 式响应,核心在于理解其代码块的 结构化边界(langn…n),而非将其视为零散符号。一次精准的正则捕获 + 内容提取,比多次模糊替换更可靠、更可维护。