【问题标题】:Regex - Return First and Last Name正则表达式 - 返回名字和姓氏
【发布时间】:2009-11-02 13:57:46
【问题描述】:

我正在寻找最可靠的方法来返回给定全名的人的名字和姓氏,到目前为止,我能想到的最好的方法是以下正则表达式:

$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”。

编辑:我知道 一些 名称不会被正确识别,但这对我来说不是问题,因为这将用于最后一个本地站点word 是姓氏(虽然可能不是整个姓氏)但这不是问题,因为我想要的只是一种快速地说“亲爱的 FIRST_NAME LAST_NAME”的方式......所以所有这些讨论,虽然完全有效,对我没用。

有人可以帮我解决这个问题吗?

【问题讨论】:

  • 你会如何处理像“Hesselink 的 Jan Vennegoor”这样的名字或姓氏在前的国家的名字?
  • 如果有人有双桶名称,即 John Wright Smith,您将开始遇到问题。正如您假设 String { } String 之间的任何内容都是中间名。
  • @Rich 和 @James - 是的,但他非常清楚地定义了姓氏的含义。
  • @Domonic,定义可能很清楚,但不适用于一大类名称。 “黑塞林克的 Vennegoor”姓:en.wikipedia.org/wiki/Jan_Vennegoor_of_Hesselink
  • Dominic,仅仅因为他以一种方式定义了这一点并不意味着他一定在做正确的事情,强调他正在尝试做的事情中可能存在的缺陷是绝对正确的。

标签: php regex string


【解决方案1】:

这可能不是你想听到的,但我认为这个问题不适合正则表达式,因为名称不是正则表达式。我认为它们甚至不是上下文敏感的或上下文无关的。如果有的话,它们是不受限制的(不过,在我肯定地说之前,我必须坐下来思考更多)并且没有正则表达式引擎可以解析不受限制的语法。

【讨论】:

  • 其实我想多了……我不认为名字是不受限制的。我认为任何形式的语言都不能用于名称。
【解决方案2】:

您可能会发现执行以下操作更容易,而不是正则表达式:

$parts = explode(" ", $name);
$first = $parts[0];
$last = ""
if (count($parts) > 1) {
    $last = $parts[count($parts) - 1];
}

您可能想先用一个空格替换多个连续的空白位,这样您就不会得到空位,并摆脱尾随/前导空格:

$name = ereg_replace("[ \t\r\n]+", " ", trim($name));

【讨论】:

  • explode 如何处理空元素 - 即是否需要先修剪 $name?此外,[ \t\r\n] 是一种相当冗长的说法 \s
【解决方案3】:

按原样,您需要姓氏 - 当然,您的第一个示例没有。

对中间名和姓氏作为一个整体使用集群分组 (?:...) 和 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】:

根据您的数据的清洁程度,我认为您将很难找到一个符合您要求的正则表达式。您希望名称采用哪些不同的格式?我不得不编写类似的代码,并且可能有很多变化: - 先到后 - 最后,第一个 - 第一个中间最后一个 - 最后,第一个中间

还有后缀(Junior、Senior、III 等)和前缀(Mr.、Mrs 等)、组合名称(例如 John 和 Mary Smith)。正如其他一些人已经提到的那样,您还必须处理多部分姓氏(例如 Victor de la Hoya)。

我发现我必须先处理所有这些可能性,然后才能可靠地提取名字和姓氏。

【讨论】:

    【解决方案5】:

    如果您将名字和姓氏定义为第一个空格之前和最后一个空格之后的文本,则只需将字符串拆分为空格并获取数组的第一个和最后一个元素。

    但是,根据您所做工作的背景/范围,您可能需要重新评估事物 - 并非世界上所有的名字都符合这种模式。

    【讨论】:

      【解决方案6】:

      我认为您最好的选择是将名字之后的所有内容都视为姓氏,即

      威廉·亨利·盖茨
      名字:威廉
      姓氏:亨利·盖茨

      这是最安全的机制,因为不是每个人都会输入他们的中间名。你不能简单地提取威廉——忽略亨利——然后提取盖茨,正如你所知,亨利是姓氏的一部分。

      【讨论】:

      • 以中间名作为姓氏并不是最安全的机制。最安全的机制 - 如果需要这些部件 - 是明确要求人们在单独的字段中提供它们。
      • 它是最安全的机制...鉴于情况。我想如果他有这个选择,他就不会处于现在的境地。
      【解决方案7】:

      这是简单的非正则表达式

      $name=explode(" ",$name);
      $first_name=reset($name);
      $last_name=end($name);
      $result=$first_name.' '.$last_name;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多