You need to enable JavaScript to run this app. PHP使用preg_split解析文本时如何保留最后一列消息完整内容
优惠活动
大模型
产品
解决方案
定价
更多

PHP使用preg_split解析文本时如何保留最后一列消息完整内容

固定列宽结构化TXT的表格渲染实现方案

问题根因

原有逐行拆分逻辑存在两个本质缺陷,直接导致渲染错位:

  • 无差别按空白字符分割所有内容,没有识别到前6列是独立固定字段、第7列Message是允许包含任意空格的长文本字段,把Message内部的正常空格也当成了字段分割符
  • 未做行类型区分:固定排版下,仅当行开头对应ADDRESS字段的位置有有效非空值时才是新记录行;开头对应前6个字段位置全为空白的行,本质是上一条Message的跨行续行,应该归属于上一条记录的Message内容,而非独立记录

核心实现逻辑

针对固定宽度对齐的TXT排版特性,调整处理规则:

  1. 放弃全局空白拆分逻辑,改为按固定字符偏移位置截取前6个固定字段,截取完成后,该行从Message列起始位置到行尾的所有内容(包含所有内部空格)直接作为该行的Message片段,不做二次拆分
  2. 增加行类型判断:
    • 若截取得到的ADDRESS字段为非空有效值,判定为新记录:先将上一条缓存的完整记录渲染为表格行,再初始化新的记录缓存
    • 若截取得到的ADDRESS字段为空,判定为上一条记录的Message续行:直接将当前行的Message片段追加到上一条缓存的Message字段末尾,不生成独立表格行
  3. 循环读取文件结束后,统一输出最后一条缓存的未渲染记录,避免漏数据

注意:所有固定字段的截取偏移长度,需要根据自身实际TXT文件的排版宽度调整,可通过打印行字符串的字符位置校验匹配

适配后的可直接运行代码

// 初始化表格结构,带表头
echo "<table border='1' cellpadding='6' cellspacing='0'>";
echo "<thead><tr>
<th>ADDRESS</th><th>TIME</th><th>DATE</th><th>MODE</th><th>TYPE</th><th>BITRATE</th><th>MESSAGE</th>
</tr></thead><tbody>";

$file_handle = fopen("lib/today.txt", "r");
$current_record = null; // 缓存当前正在拼接的记录

// 列截取规则:根据实际文件排版调整每个字段的结束位置(字符索引,从0开始)
// 参考示例排版的偏移配置:
$col_end_pos = [
    'ADDRESS' => 6,   // 第0-6位为ADDRESS字段
    'TIME' => 15,     // 第7-15位为TIME字段
    'DATE' => 23,     // 第16-23位为DATE字段
    'MODE' => 29,     // 第24-29位为MODE字段
    'TYPE' => 38,     // 第30-38位为TYPE字段
    'BITRATE' => 45   // 第39-45位为BITRATE字段,第46位开始为MESSAGE区域
];

while (!feof($file_handle)) {
    $line_of_text = rtrim(utf8_encode(fgets($file_handle)), "\r\n"); // 去掉行尾换行符,避免拼接时多余换行
    // 跳过空行
    if (empty(trim($line_of_text))) continue;

    // 按固定位置截取前6个字段
    $address = trim(substr($line_of_text, 0, $col_end_pos['ADDRESS']));
    $time = trim(substr($line_of_text, $col_end_pos['ADDRESS'], $col_end_pos['TIME'] - $col_end_pos['ADDRESS']));
    $date = trim(substr($line_of_text, $col_end_pos['TIME'], $col_end_pos['DATE'] - $col_end_pos['TIME']));
    $mode = trim(substr($line_of_text, $col_end_pos['DATE'], $col_end_pos['MODE'] - $col_end_pos['DATE']));
    $type = trim(substr($line_of_text, $col_end_pos['MODE'], $col_end_pos['TYPE'] - $col_end_pos['MODE']));
    $bitrate = trim(substr($line_of_text, $col_end_pos['TYPE'], $col_end_pos['BITRATE'] - $col_end_pos['TYPE']));
    // 从BITRATE结束位置到行尾的所有内容,就是当前行的Message片段
    $msg_part = substr($line_of_text, $col_end_pos['BITRATE']);

    // 跳过表头行
    if (trim($address) === 'ADDRESS') continue;

    if (!empty($address)) {
        // 遇到新记录,先把上一条缓存的记录渲染出来
        if ($current_record !== null) {
            echo "<tr>
                <td>{$current_record['address']}</td>
                <td>{$current_record['time']}</td>
                <td>{$current_record['date']}</td>
                <td>{$current_record['mode']}</td>
                <td>{$current_record['type']}</td>
                <td>{$current_record['bitrate']}</td>
                <td style='white-space: pre-wrap;'>{$current_record['message']}</td>
            </tr>";
        }
        // 初始化新的记录缓存
        $current_record = [
            'address' => $address,
            'time' => $time,
            'date' => $date,
            'mode' => $mode,
            'type' => $type,
            'bitrate' => $bitrate,
            'message' => trim($msg_part)
        ];
    } else {
        // 是续行,直接把Message片段拼到上一条的Message后面
        if ($current_record !== null) {
            $current_record['message'] .= "\n" . trim($msg_part);
        }
    }
}

// 循环结束后,输出最后一条未渲染的缓存记录
if ($current_record !== null) {
    echo "<tr>
        <td>{$current_record['address']}</td>
        <td>{$current_record['time']}</td>
        <td>{$current_record['date']}</td>
        <td>{$current_record['mode']}</td>
        <td>{$current_record['type']}</td>
        <td>{$current_record['bitrate']}</td>
        <td style='white-space: pre-wrap;'>{$current_record['message']}</td>
    </tr>";
}

echo "</tbody></table>";
fclose($file_handle);

实现效果说明

  • Message列保留了所有原始内容,包括内部空格、跨行的续行内容,通过CSS的white-space: pre-wrap可以让单元格内的换行正确展示,不会出现内容被拆分的问题
  • 开头为空白的续行不会再生成独立的错位表格行,所有续行内容都会归属到上一条对应记录的Message单元格中

内容的提问来源于stack exchange,提问作者relova

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.13 14:45:10