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

如何通过正则表达式将多条多行文本条目转换为单行?

问题原因分析

你原来的写法存在3个核心问题:

  • 负前瞻(?!#)位置错误,紧跟在[\s\S]+?后无法阻止匹配过程中遇到#开头的大标题边界,非贪婪模式会无规则提前截断
  • 没有覆盖每个大段最后一个条目的场景,最后一个条目后没有下一个(?[a-z0-9]+\)标识,会被正则漏掉
  • 没有兼容子条目(a)、b)类)的多行匹配需求
正确实现方案

核心逻辑是匹配所有行首为(数字) 或小写字母) 开头的条目,捕获条目内容直到下一个条目边界/大标题边界/文本末尾,再将内容中的换行、多余空白替换为单个空格。

// 匹配条目的正则:m多行模式,s点号匹配换行
$pattern = '/^([(]?[a-z0-9]+[)] )(.*?)(?=$|^\(?[a-z0-9]+\)|^#)/ms';

$text = preg_replace_callback($pattern, function ($grp) {
    // unwrap逻辑:替换换行、制表符为单个空格,去除多余空格
    $unwrapContent = preg_replace('/\s+/', ' ', trim($grp[2]));
    return $grp[1] . $unwrapContent . PHP_EOL;
}, $text);

代码说明

  • 正则修饰符用ms:m开启多行模式让^匹配每行行首,s让.匹配换行符,代替原来的[\s\S]写法更简洁
  • 用正前瞻(?=$|^\(?[a-z0-9]+\)|^#)做边界判断:匹配到文本末尾、下一个条目开头、下一个大标题开头三个边界任意一个就停止捕获,不会漏匹配最后一个条目
  • 内置unwrap逻辑直接完成换行、缩进空白的替换,不需要额外定义自定义函数
效果示例

处理前的(3)条目:

(3) Here is the problem, text for each numbered line is
supposed to be on a single line like in (1) and (2), but
the text often spans multiple lines of text.

处理后:

(3) Here is the problem, text for each numbered line is supposed to be on a single line like in (1) and (2), but the text often spans multiple lines of text.

内容的提问来源于stack exchange,提问作者Coffee'd Up Hacker

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 02:39:02