
本文介绍一种使用正向/负向零宽断言构建的正则表达式,可严格匹配形如 **text** 的模式,确保首尾恰好为两个星号、且不被更多星号包围(如 ***text*** 不会被误匹配)。
本文介绍一种使用正向/负向零宽断言构建的正则表达式,可严格匹配形如 `**text**` 的模式,确保首尾恰好为两个星号、且不被更多星号包围(如 `***text***` 不会被误匹配)。
要实现“仅匹配两侧各有两个星号、且星号不连续超过两个”的目标,关键在于排除星号的相邻干扰——即要求开头的 ** 前不能有星号,其后也不能紧接第三个星号;同理,结尾的 ** 前不能是星号(保证它是闭合的起始),其后也不能是星号(防止它是更长星号序列的一部分)。
推荐使用的正则表达式如下(支持 PCRE、JavaScript、Python re 等主流引擎):
(?<!\*)\*{2}(?!\*).*?(?<!\*)\*{2}(?!\*)✅ 各部分解析:
(?:<strong>负向先行断言</strong>,确保当前位置之前<strong>没有 <code>**(即开头两个星号不能是 `` 的后半部分);-
\*{2}:字面量匹配**; -
(?!\*):负向先行断言,确保**后紧跟的字符不是**(排除 `` 开头); -
.*?:非贪婪匹配任意内容(换行符除外;如需跨行,请启用s标志或改用[\s\S]*?); (?:对结尾 <code>**施加同等限制——它前面不能是*(避免***中间重叠),后面也不能是*(避免后续还有星号)。
⚠️ 注意事项:
- 在 JavaScript 中,
(?(负向后行断言)自 ES2018 起才被广泛支持;若需兼容旧环境,可改用 <code>(^|\W)\*{2}(?!\*)(.*?)(? 并捕获第2组(<code>$2),再手动替换,但逻辑更复杂; - 若目标文本含换行符,建议添加
s(single-line)标志(如 Python 中re.DOTALL,或 regex101 中勾选s),使.匹配换行符; - 实际替换时,推荐使用带捕获组的版本提取内容(如
(?),便于复用内部文本而非硬编码 <code>"Test"。
? 示例验证(Python):
import re
pattern = r'(?<!\*)\*{2}(?!\*)(.*?)(?<!\*)\*{2}(?!\*)'
text = "Here is **Car**, not ***Bird***, and **This is a test**."
result = re.sub(pattern, r'"Test"', text)
print(result) # 输出:Here is "Test", not ***Bird***, and "Test".该方案通过精确控制边界条件,彻底规避了传统 \*{2}[\w\s]+\*{2} 导致的过度匹配问题,是处理 Markdown 风格强调语法、模板占位符等场景的稳健实践。

















