
本文介绍一种健壮的正则方案,用于从多行文本中匹配 #%META 与 #%ENDS 之间的所有内容块,并自动剥离每行开头的 # 及其后空格,适用于配置文件、模板元数据等场景。
本文介绍一种健壮的正则方案,用于从多行文本中匹配 `#%meta` 与 `#%ends` 之间的所有内容块,并自动剥离每行开头的 `#` 及其后空格,适用于配置文件、模板元数据等场景。
在处理结构化注释块(如 #%META / #%ENDS 包裹的元数据)时,常见误区是依赖简单贪婪匹配或忽略换行边界,导致跨块捕获、遗漏或无法清除注释符。以下正则表达式专为精确分块 + 安全清理而设计:
^#%META((?>\R(?!#%(?:META|ENDS)$).*)+)\R#%ENDS$
该模式使用 m(multiline)标志启用行首/行尾锚点 ^ 和 $ 的逐行匹配能力,并通过原子组 (?>...) 避免回溯灾难,确保高效且稳定地捕获每个独立的 #%META–#%ENDS 区段。
关键特性解析:
-
^#%META:严格匹配行首的#%META; -
((?>\R(?!#%(?:META|ENDS)$).*)+):核心捕获组,其中:-
\R匹配任意 Unicode 换行符(兼容\n,\r\n,\r); -
(?!#%(?:META|ENDS)$)否定前瞻,确保下一行不是#%META或#%ENDS,从而天然隔离区块; -
.*匹配该行剩余全部内容(含空格); - 原子组
(?>...)防止引擎在失败时反复回溯,提升性能与可靠性;
-
-
\R#%ENDS$:严格匹配紧接着的换行符 + 行尾的#%ENDS。
⚠️ 注意事项:
- 必须启用
m标志(如 PHP 中/.../m,Python 中re.MULTILINE),否则^和$不作用于每行; - 不要使用
s(dotall)标志——此处需显式用\R控制换行,避免误吞#%ENDS; - 捕获内容默认包含换行符,后续需用
trim()清理首尾空白; - 清理
#注释符推荐使用^#\h*(m模式下)配合preg_replace,\h匹配水平空白(空格、制表符等),比\s更安全(避免误删行尾换行)。
完整 PHP 示例:
$re = '/^#%META((?>\R(?!#%(?:META|ENDS)$).*)+)\R#%ENDS$/m';
if (preg_match_all($re, $str, $matches)) {
$result = array_map(function ($block) {
return preg_replace("/^#\h*/m", "", trim($block));
}, $matches[1]);
}
// $result 即为两个纯净元数据字符串组成的数组该方案可无缝迁移至 Python(re.findall(re_str, text, re.MULTILINE))、JavaScript(/.../gm + .matchAll())等主流语言,核心逻辑一致:先精确定界,再后处理清洗——这是处理多行结构化注释最可靠、可维护性最强的实践路径。

















