
本文介绍使用PHP的preg_match_all()函数,通过不区分大小写的正则匹配,统计预定义作者姓氏列表中每个姓氏在长文本中的出现频次,并自动返回出现次数最多的姓氏(即主作者),适用于学术文章、出版物等场景下的作者识别需求。
本文介绍使用php的`preg_match_all()`函数,通过不区分大小写的正则匹配,统计预定义作者姓氏列表中每个姓氏在长文本中的出现频次,并自动返回出现次数最多的姓氏(即主作者),适用于学术文章、出版物等场景下的作者识别需求。
在处理学术文献、新闻稿或结构化文本时,常需从大段文字中自动识别“核心提及对象”——例如,从一篇综述文章中定位被反复提及的作者,其姓氏即为关键线索。本文提供一个轻量、高效且鲁棒的PHP解决方案:给定一个约150个作者姓氏组成的数组(如 ['Smith', 'Jackson', 'Peters'])和一段含自然语言的长文本字符串,精准识别出在文本中出现频次最高(且至少出现两次)的姓氏,并将其作为主作者返回。
核心逻辑基于 preg_match_all() 函数,它支持正则表达式全局匹配并返回匹配总数。我们为每个姓氏构造不区分大小写的字面量模式(如 /Smith/i),避免误匹配子串(如 ‘Peters’ 匹配到 ‘Peterson’ 的风险较低,但若需更严格匹配词边界,可升级为 /\bSmith\b/i)。完整实现如下:
$getAuthor = function(string $text, array $familyNames): string {
$scores = [];
foreach ($familyNames as $name) {
// 使用 \b 确保匹配完整单词(推荐用于姓名防误匹配)
$pattern = '/\b' . preg_quote($name, '/') . '\b/i';
$count = preg_match_all($pattern, $text);
$scores[$name] = $count;
}
// 按频次降序排序,保持键名关联
arsort($scores);
// 返回出现次数最高的姓氏(第一个键)
return key($scores);
};
// 示例调用
$text = 'Lorem ipsum dolor sit amet, Smith consectetur adipiscing elit.
Johnson Donec a diam lectus. Sed sit amet ipsum mauris
Smith Maecenas congue ligula ac quam viverra Smith nec consectetur
ante hendrerit.
Smith Donec et mollis dolor. Praesent et diam eget libero egestas
mattis sit amet vitae augue.
Nam tincidunt congue enim, ut porta Johnson lorem lacinia
consectetur.';
$familyNames = ['Smith', 'Johnson', 'Peters', 'Lorem'];
$mainAuthor = $getAuthor($text, $familyNames);
echo "主作者:{$mainAuthor}(共出现 {$scores[$mainAuthor]} 次)"; // 输出:主作者:Smith(共出现 4 次)✅ 关键优化说明:
- 使用
preg_quote($name, '/')对姓氏中可能存在的正则元字符(如.,*,+)进行转义,防止语法错误; - 添加
\b(单词边界)确保只匹配独立词汇,避免‘Lee’错误匹配‘Leeds’或‘Greenlee’; -
arsort()保留关联键,使结果语义清晰; - 函数签名明确标注类型提示(PHP 7.0+),增强可维护性。
⚠️ 注意事项:
立即学习“PHP免费学习笔记(深入)”;
- 若多个姓氏并列最高频次(如均为2次),该方案返回字典序首个匹配项(因
arsort在相等值时不保证稳定顺序);如需严格返回首个达到最高频次的姓氏,可改用遍历+记录最大值的方式; - 大规模文本(>1MB)或超长姓氏列表(>1000)建议结合缓存或分块处理以优化性能;
- 如需区分大小写匹配(如
‘MacDonald’≠‘macdonald’),移除i修饰符即可。
该方法简洁、无外部依赖,开箱即用,是文本关键词频次分析的典型PHP实践范例。



















