
本教程详解如何使用 PHP 的 preg_replace 配合 (*SKIP)(*F) 回溯控制动词,从混杂文本中仅保留 #、换行符,以及包含至少一个数字的完整括号结构((...)、[...]、{...}),其余字符(包括括号内非数字内容、空格、字母、符号等)一律清除。
本教程详解如何使用 php 的 `preg_replace` 配合 `(*skip)(*f)` 回溯控制动词,从混杂文本中**仅保留 `#`、换行符,以及包含至少一个数字的完整括号结构(`(...)`、`[...]`、`{...}`)**,其余字符(包括括号内非数字内容、空格、字母、符号等)一律清除。
在文本清洗任务中,常需“保留特定模式,删除其余一切”。本例典型场景是解析日志、配置片段或结构化注释——例如只关心带编号的条目(如 #(1296)、{20}),而忽略所有描述性文字(如 (MONDAY )、(BEACH 7)、[20 Mtrs])和多余空格。
核心难点在于:不能简单保留所有括号对,而必须筛选出“内部至少含一个数字”的括号结构;同时要保留 # 和换行符以维持基本格式骨架。
✅ 正确正则表达式如下:
$re = '/(?:\[\h*\d[\h\d]*]|\(\h*\d[\h\d]*\)|{\h*\d[\h\d]*})\h*(*SKIP)(*F)|[^#\n]/';
$result = preg_replace($re, '', $input);
? 表达式解析:
-
(?:...):非捕获分组,用于逻辑组合; -
\[\h*\d[\h\d]*]:匹配方括号内至少一个数字(允许前后有水平空白,如{ 03 Foot }中的{20}被保留,但{ 03 Foot }整体不匹配,因含字母); -
\(\h*\d[\h\d]*\)和{\h*\d[\h\d]*}同理,分别匹配含数字的圆括号与花括号; -
\h*在括号结构后额外匹配后续水平空白(如空格),确保清理后括号间不残留孤立空格; -
(*SKIP)(*F):关键指令——一旦匹配到合法括号结构(含数字),立即跳过(SKIP)并强制失败(FAIL),使其原样保留,不参与替换; -
|[^#\n]:其余所有字符(除#和换行符\n外)均被匹配并替换为空字符串。
⚠️ 注意事项:
-
\h匹配水平空白(空格、制表符等),不包括换行符,避免误吞行结构; - 不使用
.*?等贪婪/懒惰量词,防止跨括号误匹配; - 若输入含 Unicode 数字(如全角数字),需添加
u修饰符并调整\d为\p{N}; - 测试时建议启用
m(多行)修饰符以确保^/$行锚点行为正确(本例未依赖,但可增强健壮性)。
? 总结:该方案通过 (*SKIP)(*F) 实现“白名单式过滤”,比否定逻辑更清晰可靠。它不依赖预处理或多次替换,单次正则即可达成目标——既精简代码,又保障可维护性与执行效率。










