应使用 preg_split('/(?

用 preg_split 保留换行和缩进分割文本
PHP 默认的 explode("\n", $text) 会直接丢掉换行符,更不会保留每行开头的空格或制表符。要真正“按行分割但保留原始缩进”,得靠正则——关键是匹配换行位置,而不是消耗换行符本身。
推荐写法:preg_split('/(? 不行,它会在换行后切,但首行没前导 \n,会漏掉;正确思路是匹配行尾(包括 \n 或 \r\n),但不捕获、不移除,用零宽断言锚定位置。
- ✅ 推荐正则:
/(? —— 行尾后切,保留所有前置空白 - ⚠️ 注意:Windows 换行是
\r\n,Linux/macOS 是\n,必须同时覆盖 - ⚠️
PREG_SPLIT_DELIM_CAPTURE会把换行符也当元素返回,一般不需要;只加PREG_SPLIT_NO_EMPTY防空行即可 - ? 实际示例:
$lines = preg_split('/(?
为什么不用 file() 或 str_split
file() 确实能读行并保留换行符(取决于 FILE_IGNORE_NEW_LINES 是否关闭),但它专为文件设计,对内存中字符串不适用;str_split($text, 1) 是按字符拆,完全不解决“按行+保缩进”问题。
- ❌
file('php://stdin')或file('data:text/plain;base64,...')属于绕路操作,不可控且低效 - ❌
str_replace+explode组合容易破坏内容里原有的换行或空格(比如缩进含多个空格时被误处理) - ✅ 唯一干净路径:用
preg_split配合正确的断言模式,不修改原文,只切位置
缩进包含制表符时需额外注意正则边界
如果原始文本缩进混用空格和 \t,而你后续还要做缩进层级分析(比如解析 YAML/Python 风格缩进),光靠分割不够——分割只是第一步,缩进本身仍完整保留在每行开头的 $lines[0] 字符串里。
立即学习“PHP免费学习笔记(深入)”;
- ✅ 检查某行缩进长度:
strlen($lines[0]) - strlen(ltrim($lines[0])) - ⚠️
ltrim($line, " \t")比单纯ltrim($line)更安全,避免误删中文全角空格等 - ⚠️ 正则中若用
[\r\n]替代\r\n|\n,会把\r和\n当作独立换行符处理,导致\r\n被错切成两段
性能与大文本场景下的实际取舍
对几 KB 的配置片段,preg_split 没压力;但若处理 MB 级日志或模板,反复正则扫描可能变瓶颈。这时可退回到手动遍历:
- ✅ 用
strpos+substr循环找\n和\r\n,边找边截取,内存友好、无正则开销 - ⚠️ 手动实现要注意:先找
\r\n,再找\n,否则\r\n会被拆成两个单字符换行 - ? 小技巧:用
str_replace("\r\n", "\n", $text)统一换行符再explode("\n", ...),虽丢失原始换行格式,但对多数文本处理已够用
真正难的不是切分动作本身,而是切完之后怎么判断哪一行属于上一行的子块——那得靠缩进量比较,不是正则能解决的。











