You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用正则使提取结果包含换行内容(PHP preg_match_all场景)

解决方案

核心思路

原来的问题出在没有给消息内容设置明确的终止匹配边界,所以要么匹配不到换行,要么加了单行模式就直接匹配到文件尾。我们可以用负向正向预查让消息内容匹配时,遇到下一条消息的日期头就停止,就可以完美兼容消息内换行的场景。

修正后的正则

/(?<date>(?:[0-9]{1,2}\/){2}[0-9]{1,2}),\s(?<time>(?:[0-9]{1,2}:)[0-9]{2}\s[ap]m)\s-\s(?<name>[^:]+):\s(?<message>(?s:(?!^\d{1,2}\/\d{1,2}\/\d{1,2}).)*)/m

改动点说明

  • 给整个正则加了m多行修饰符,让^可以匹配每一行的开头,用来识别下一条消息的起始位置
  • name分组从.*改成[^:]+,避免不必要的回溯,匹配到冒号就停止,更精准
  • message分组逻辑改成:开启单行模式(.匹配换行)的前提下,每匹配一个字符前都检查当前位置是不是下一条消息的日期开头,如果不是就继续匹配,直到碰到消息头或者文件尾
  • 原来写法里[a|p]m的竖线是多余的,字符组里不需要加或逻辑,直接写[ap]m即可

PHP调用示例

<?php
$content = file_get_contents('你的消息文件路径.txt');
$pattern = '/(?<date>(?:[0-9]{1,2}\/){2}[0-9]{1,2}),\s(?<time>(?:[0-9]{1,2}:)[0-9]{2}\s[ap]m)\s-\s(?<name>[^:]+):\s(?<message>(?s:(?!^\d{1,2}\/\d{1,2}\/\d{1,2}).)*)/m';
preg_match_all($pattern, $content, $matches, PREG_SET_ORDER);

// 按需处理结果
$result = [];
foreach ($matches as $match) {
    $result[] = [
        'date' => $match['date'],
        'time' => $match['time'],
        'name' => $match['name'],
        'message' => rtrim($match['message']) // 去掉末尾多余换行
    ];
}

print_r($result);

结果说明

按你的示例文件处理后,所有跨换行的消息内容都会自动拼接到对应message字段中,不会丢失内容,比如第二条消息的内容会完整保留为:

Here is yet another message
where someone added a line break

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 14:24:05