
本文介绍如何使用 PHP 对多行文本进行逐行处理,识别并保留 {19} 和 {20} 等指定花括号标记在原位置,同时将其他形如 {n} 的标记统一移至每行末尾,兼顾可读性与正则精准匹配。
本文介绍如何使用 php 对多行文本进行逐行处理,识别并保留 `{19}` 和 `{20}` 等指定花括号标记在原位置,同时将其他形如 `{n}` 的标记统一移至每行末尾,兼顾可读性与正则精准匹配。
在日志预处理、配置文件规范化或模板文本清洗等场景中,常需基于语义规则对特定格式标记(如 {数字})进行位置重排。本例目标明确:仅保留 {19} 和 {20} 在原始位置,其余所有 {n} 形式标记(如 {15}、 {29}、 {21})须整体迁移至所在行末尾,且保持原有顺序不变(但按题目示例要求,最终输出中这些被移动项为「逆序」排列——即最后匹配的先输出,详见后文说明)。
实现核心在于「分而治之」:先按行切分,再逐行拆词、分类、重组。以下是推荐的健壮实现方案:
<?php
$input = <<<TEXT
# (811) (1485) [2756] {29} [555] {15}
# (811) (1476) {20} {15} (1485) [196] [2441]
# (911) (619) {19} (1476) [2765] [2752] {21}
TEXT;
foreach (explode("\n", trim($input)) as $line) {
if ($line === '') continue; // 跳过空行
$parts = explode(' ', $line);
$result = array_reduce($parts, function ($acc, $token) {
// 使用负向先行断言:匹配 { 后不紧接 19} 或 20} 的 {n} 模式
if (preg_match('/^{(?!19}|20})\d+}/', $token)) {
$acc['move'][] = $token;
} else {
$acc['valid'][] = $token;
}
return $acc;
}, ['valid' => [], 'move' => []]);
// 注意:题目示例输出中被移动项为「逆序」(如第一行 {15} {29} → 原序是 {29} {15})
// 故此处使用 array_reverse;若需保持原序,则直接 $result['move']
echo implode(' ', array_merge($result['valid'], array_reverse($result['move']))) . "\n";
}
?>关键点解析:
- ✅ 正则设计精要:/{(?!19}|20})\d+}/ 利用 (?!...) 负向先行断言,确保 { 后不立即出现 19} 或 20},从而精准排除白名单项。注意 20} 中的 } 是字面量,无需转义(因在字符组外且非特殊元字符)。
- ✅ 分类逻辑清晰:array_reduce 初始化双桶数组 ['valid' => [], 'move' => []],避免多次遍历,提升可维护性。
- ✅ 空行防护:trim($input) 与 if ($line === '') continue 防止空白行干扰输出。
- ⚠️ 顺序说明:示例输出中 {15} {29} 表明被移动项以「后出现者优先」排列(即原序列中靠后的 {29} 反而排在 {15} 之后),故代码采用 array_reverse($result['move'])。若业务需严格保持原始出现顺序,删去 array_reverse() 即可。
- ? 扩展建议:如需支持更多白名单(如 {19}, {20}, {25}),正则可改为 /{(?!19}|20}|25})\d+}/;若白名单动态传入,建议构建正则字符串并 preg_quote 安全转义。
该方案简洁、高效、符合 PSR-12 编码规范,可直接集成至 CLI 工具或 Web 后端文本处理器中。
立即学习“PHP免费学习笔记(深入)”;



















