
本文介绍一种稳健的 php 实现方案:将长文本智能切分为多个子块,每块严格控制在指定长度(如 500 字符)以内,同时确保句子边界完整,绝不跨句截断。核心思路是先精准分句,再贪心合并,兼顾准确性与实用性。
本文介绍一种稳健的 php 实现方案:将长文本智能切分为多个子块,每块严格控制在指定长度(如 500 字符)以内,同时确保句子边界完整,绝不跨句截断。核心思路是先精准分句,再贪心合并,兼顾准确性与实用性。
在处理用户协议、法律文本或 API 内容分片等场景时,简单按字符数 str_split() 或 chunk_split() 会粗暴切断句子,导致语义断裂、解析失败或用户体验下降。真正的挑战在于:既要尊重自然语言的句末标点(如 .、!、?),又要避免因缩写(如 “e.g.”、“Dr.”)、小数(如 “3.14”)或引号嵌套引发误分割。
✅ 推荐方案:基于正则的鲁棒分句 + 贪心归并
以下实现采用更可靠的句子切分逻辑——使用 preg_split() 匹配「后跟空白字符的句末标点」,并保留分隔符(通过 PREG_SPLIT_DELIM_CAPTURE),从而避免丢失句号;随后逐句累加,动态判断是否超出阈值:
<?php
function splitTextIntoSentenceBlocks(string $text, int $maxChars = 500): array
{
// 使用正则安全分句:匹配 . ! ? 后紧跟空白或字符串结尾,保留标点
$sentences = preg_split('/([.!?])\s+/', $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
$blocks = [];
$currentBlock = '';
for ($i = 0; $i < count($sentences); $i += 2) {
// 句子主体(可能含前导空格) + 标点(索引 i+1)
$sentence = $sentences[$i];
$punctuation = ($i + 1 < count($sentences)) ? $sentences[$i + 1] : '';
$fullSentence = trim($sentence) . $punctuation;
// 若当前块为空,或加入本句后仍 ≤ maxChars,则合并
if ($currentBlock === '' || strlen($currentBlock . $fullSentence) <= $maxChars) {
$currentBlock .= $fullSentence;
} else {
// 超长:保存当前块,重置并放入新句
if ($currentBlock !== '') {
$blocks[] = $currentBlock;
}
$currentBlock = $fullSentence;
}
}
// 添加最后一块(非空时)
if ($currentBlock !== '') {
$blocks[] = $currentBlock;
}
return $blocks;
}
// 示例用法
$text = "Hello world. This is a short sentence! And here's another one? " .
"This sentence is much longer and contains numbers like 3.14 and abbreviations e.g. this one. " .
"Final sentence ends with exclamation!";
$blocks = splitTextIntoSentenceBlocks($text, 50);
print_r($blocks);
?>⚠️ 关键注意事项
- 标点识别局限性:该方案默认以 . ! ? 为句子终点,但无法 100% 处理所有边缘情况(如英文引号内句号 "He said 'Hello.'")。如需更高精度,建议集成 NLP 库(如 spacy via Python bridge)或商用分句 API。
- 空白处理:trim() 移除句子首尾冗余空格,避免因格式问题意外超限。
- 性能提示:对超长文本(>10MB),建议分段流式处理,避免内存溢出。
- 中文兼容性:若文本含中文,需扩展正则为 /([.!?。!?])\s*/u 并启用 UTF-8 模式(u 修饰符),确保正确匹配中文标点。
✅ 总结
与其依赖脆弱的 explode('. ')(易被缩写干扰),不如采用带捕获的正则分句 + 显式长度校验的组合策略。它平衡了实现复杂度与生产可用性,可稳定服务于日志归档、LLM 提示词分片、多段落邮件生成等真实需求。记住:句子完整性永远优先于字符数精确性——宁可让某块略短,也绝不可让一句横跨两块。











