使用前缀提取姓氏的正则表达式

时间:2014-05-12 13:23:28

标签: regex preg-match names

有没有办法可以使用正则表达式或其他逻辑从字符串中提取名称的一部分。

我想用空格分割名称,但如果名称带有前缀,我想拆分前缀,例如。

Osama bin Laden bin Mohammed => Osama, bin Laden, bin Mohamed
Jorge do Pinto da Silva => Jorge, do Pinto, da Silva
John Andrew Smith => John, Andrew, Smith
José Mário dos Santos Mourinho Félix => José, Mário, dos Santos, Mourinho, Félix

基于Tim建议的工作代码

$str = 'Manuel D\'Souza do Pinto bin Laden Al-saud el Mecca de la Vere Na Sokakah van Der Reidejin del Monte du Pont ter Johannes';
preg_match_all( '~\b(von der|van de|van den|del la|de la|van der|vande|vanden|vander|st|der|des|dela|della|bin|dos|ur|ibn|bint|da|do|le|la|del|du|de|di|el|al|van|von|ter|na|del|san|los)\s+[^\s]+\b|\b[^\s]+~i', $str, $mat );
print_r( $mat );

结果:

Array(
[0] => Array
    (
        [0] => Manuel
        [1] => D'Souza
        [2] => do Pinto
        [3] => bin Laden
        [4] => Al-saud
        [5] => el Mecca
        [6] => de la Vere
        [7] => Na Sokakah
        [8] => van Der Reidejin
        [9] => del Monte
        [10] => du Pont
        [11] => ter Johannes
    )

[1] => Array
    (
        [0] => 
        [1] => 
        [2] => do
        [3] => bin
        [4] => 
        [5] => el
        [6] => de la
        [7] => Na
        [8] => van Der
        [9] => del
        [10] => du
        [11] => ter
    )

3 个答案:

答案 0 :(得分:3)

记住所有falsehoods programmers believe about names,你仍然可以尝试

\b\p{Lu}\p{Ll}*|\b\p{Ll}+\s+\p{Lu}\p{Ll}*

将匹配大写单词(name)或小写前缀,后跟大写单词。

live on regex101.com

<强>解释

\b      # Start of word
\p{Lu}  # One uppercase letter
\p{Ll}* # Any number of lowercase letters
|       # or
\b      # Start of word
\p{Ll}+ # One or more lowercase letters
\s+     # Whitespace
\p{Lu}  # One uppercase letter
\p{Ll}* # Any number of lowercase letters

答案 1 :(得分:2)

因为问题是关于使用拆分。这是一个应该有效的正则表达式:

$re = '/\b(?<!-)(?>\p{Ll}+|\p{L}{1,3}) +(*SKIP)(*FAIL)| +/u';
$str = 'Manuel D\'Souza do Pinto bin Laden Al-saud el Mecca de la Vere Na Sokakah van Der Reidejin del Monte du Pont ter Johannes';
print_r( preg_split($re, $str) );

输出:

Array
(
    [0] => Manuel
    [1] => D'Souza
    [2] => do Pinto
    [3] => bin Laden
    [4] => Al-saud
    [5] => el Mecca
    [6] => de la Vere
    [7] => Na Sokakah
    [8] => van Der Reidejin
    [9] => del Monte
    [10] => du Pont
    [11] => ter Johannes
)
  • (*FAIL)表现得像一个失败的否定断言,是(?!)
  • 的同义词
  • (*SKIP)定义了一个点,当子模式稍后失败时,不允许正则表达式引擎回溯
  • (*SKIP)(*FAIL)一起提供了一个限制的替代方法,你不能在上面的正则表达式中使用可变长度的lookbehinf。

答案 2 :(得分:1)

您可以使用此正则表达式:

[a-z]+\s[A-Z][a-z]+|[A-Z][a-z]+

以上将与那些相匹配。所以你不需要拆分。只是匹配它们。

它正在做的是,它寻找小套管字加空格,然后单独寻找名称或名称。

另请注意,除了英语之外,它会在不同的重音符号上失败。

Demo