我正在寻找最好的可靠方式返回给出全名的人的名字和姓氏,到目前为止,我能想到的最好的是以下正则表达式:
$name = preg_replace('~\b(\p{L}+)\b.+\b(\p{L}+)\b~i', '$1 $2', $name);
预期的输出应该是这样的:
William -> William // Regex Fails
William Henry -> William Henry
William Henry Gates -> William Gates
我还想要支持口音,例如“João”。
编辑:我知道某些名称将无法正确识别,但这对我来说不是问题,因为这将在最后一个本地网站上使用单词是姓氏(可能不是整个姓氏),但这不是问题,因为我想要的是一个快速的方式来说“亲爱的FIRST_NAME LAST_NAME”... 所有这些讨论,同时完全有效,对我没用。
有人可以帮我这个吗?
答案 0 :(得分:7)
这可能不是您想听到的,但我不认为此问题适合于正则表达式,因为名称不是常规的。我不认为他们甚至是上下文敏感或无上下文。如果有的话,它们是不受限制的(我必须坐下来思考,而不是在我说之前我做过的事情),并且没有正则表达式引擎可以解析不受限制的语法。
答案 1 :(得分:6)
而不是正则表达式,您可能会发现更容易做类似的事情:
$parts = explode(" ", $name);
$first = $parts[0];
$last = ""
if (count($parts) > 1) {
$last = $parts[count($parts) - 1];
}
您可能希望首先用一个空格替换多个连续的空白位,这样就不会得到空位,并且摆脱尾随/前导空格:
$name = ereg_replace("[ \t\r\n]+", " ", trim($name));
答案 2 :(得分:2)
根据您的数据的清洁程度,我认为您将很难找到符合您需要的单一正则表达式。您希望名称有哪些不同的格式?我必须编写类似的代码,可能会有很多变化: - 最后一个 - 最后,第一个 - 中间的第一个中间 - 最后,第一个中间
然后你有后缀(少年,大四,三等)和前缀(先生,夫人等),组合名称(如约翰和玛丽史密斯)。正如其他一些人已经提到的那样,你也必须处理多部分的姓氏(例如Victor de la Hoya)。
我发现在能够可靠地取出名字和姓氏之前,我必须处理所有这些可能性。
答案 3 :(得分:2)
按原样,你需要一个姓氏 - 这当然是你的第一个例子。
使用群集分组,(?:...)
和0或1计数?
作为整体的中间名和姓氏,以允许它们是可选的:
'~\b(\p{L}+)\b (?: .+\b(\p{L}+)\b )?~ix' # x for spacing
这应该允许捕获名字,无论是否给出中间/姓氏。
$name = preg_replace('~\b(\p{L}+)\b(?:.+\b(\p{L}+)\b)?~i', '$1 $2', $name);
答案 4 :(得分:1)
如果您将名字和姓氏定义为第一个空格之前和最后一个空格之后的文本,那么只需将字符串拆分为空格并抓住数组的第一个和最后一个元素。
但是,根据您正在做的事情的背景/范围,您可能需要重新评估事物 - 并非世界上所有名称都符合此模式。
答案 5 :(得分:1)
我认为你最好的办法是简单地将名字后的所有名字都当作姓氏处理,即
William Henry Gates
姓:威廉
姓:亨利盖茨
这是最安全的机制,因为不是每个人都会输入他们的中间名。你不能简单地提取威廉 - 忽略亨利 - 并提取盖茨就像你所知道的那样,亨利是姓氏的一部分。
答案 6 :(得分:0)
这是简单的非正则表达方式
$name=explode(" ",$name);
$first_name=reset($name);
$last_name=end($name);
$result=$first_name.' '.$last_name;