
本文介绍使用PHP的preg_match_all()函数,结合正则表达式与排序逻辑,高效比对长文本与预定义姓氏列表,精准定位出现频次最高的作者姓氏(即主作者),并返回该姓名字符串。
本文介绍使用php的`preg_match_all()`函数,结合正则表达式与排序逻辑,高效比对长文本与预定义姓氏列表,精准定位出现频次最高的作者姓氏(即主作者),并返回该姓名字符串。
在学术文章、新闻稿或出版物处理场景中,常需从大段文本中自动识别“核心提及人物”——例如,当已知150位作者的姓氏列表时,若某位作者的姓氏在文中出现频次显著高于其他作者,则可判定其为本文主作者。PHP 提供了简洁而强大的方案:无需分词或NLP库,仅用原生正则与数组操作即可实现。
核心思路是:对每个候选姓氏,在文本中执行不区分大小写的全局匹配计数,汇总频次后降序排列,取首位即为最高频作者姓氏。
以下为完整可运行示例:
<?php
$getPrimaryAuthor = function(string $text, array $familyNames): string {
$scores = [];
foreach ($familyNames as $name) {
// 使用 preg_quote() 防止姓氏中含正则特殊字符(如 '.', '+', '*' 等)导致匹配异常
$escapedName = preg_quote($name, '/');
$count = preg_match_all("/$escapedName/i", $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.
Donec ut libero sed arcu vehicula ultricies a non tortor.';
$familyNames = ['Smith', 'Johnson', 'Lorem', 'Peters', 'Jackson'];
echo $getPrimaryAuthor($text, $familyNames); // 输出:Smith
?>✅ 关键优化说明:
立即学习“PHP免费学习笔记(深入)”;
- 使用
preg_quote($name, '/')对姓氏进行转义,避免如O'Reilly、St.John或含点号/括号的姓氏引发正则语法错误; -
/i修饰符确保大小写不敏感匹配(如匹配"SMITH"、"smith"、"Smith"均有效); -
arsort()保留键值关联并按值降序排列,key($scores)安全获取最高频姓氏; - 函数严格声明参数类型(
string和array)与返回类型(string),提升可维护性与IDE支持。
⚠️ 注意事项:
- 若多个姓氏并列最高频(如
Smith:3,Johnson:3),本方案默认返回字典序最先匹配的那个(因arsort()在值相等时保持原始顺序)。如需随机返回或返回全部并列项,可扩展逻辑(例如用array_keys($scores, max($scores))获取所有最高频键); - 当文本极大(>10MB)且姓氏列表很长时,建议缓存编译后的正则模式或改用
strpos()循环提升性能; - 如需精确单词匹配(避免
"Smithson"匹配到"Smith"),应将正则升级为/\b{$escapedName}\b/i,其中\b表示单词边界。
该方法轻量、可靠、零依赖,适用于CMS插件、文献元数据提取、内容分析脚本等实际工程场景。



















