应使用 preg_split('/(?
preg_split 保留换行和缩进分割文本PHP 默认的 explode("\n", $text) 会直接丢掉换行符,更不会保留每行开头的空格或制表符。要真正“按行分割但保留原始缩进”,得靠正则——关键是匹配换行位置,而不是消耗换行符本身。
推荐写法:preg_split('/(? 不行,它会在换行后切,但首行没前导 \n,会漏掉;正确思路是匹配行尾(包括 \n 或 \r\n),但不捕获、不移除,用零宽断言锚定位置。
/(? —— 行尾后切,保留所有前置空白
\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] 字符串里。
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", ...),虽丢失原始换行格式,但对多数文本处理已够用真正难的不是切分动作本身,而是切完之后怎么判断哪一行属于上一行的子块——那得靠缩进量比较,不是正则能解决的。