2011-05-17 98 views
3

我想要解析某个字符串的名字。我想要取出字符串并将其删除,以便只有第一个名字会出现在字符串中。用空白修剪一个字符串

假设我有一个名字像这样

Mr. John Doe 
John Smith. 

在这两种情况下,我想只得到字符串的第一个名字,并删除所有其它字符。

所以对于之后他们已经将解析上对他们有John

我想知道是否有办法用正则表达式来做到这一点问题都串。

回答

6

你不能做到这一点。不是没有烦人的人,因为你已经毁了他们的名字。你不能区分John Paul Doe(名字“John”,中间名“Paul”,姓氏“Doe”),John Joseph Brown(回答“Joseph”或“Joe”,但只使用“John”政府表格)和约翰保罗史密斯(约翰保罗的第一个名字,并且不愿意缩短)。

阅读Falsehoods Programmers Believe About Names

然后再读一遍,这一次接受,是的,世界上95%的人口都有一个完全不同的想法,即你的名字是什么。 (80%,如果你是中国人)。

你可以做的最多的是截断空白,也许几个“安全”的前缀,如“先生” - 我甚至不会这样做(如果人们困扰写“先生”,他们大概喜欢在那里)。

s/^\s+//; s/\s+$//;  # trim whitespace at each end 
s((\s+))(    # trim embedded whitespace 
    $1=~/[^\x{a0}]/ ? # breakable? 
    " " : "\x{a0}")ge; 
+3

这篇文章高度夸大了这个问题。它还假定OP有全世界的观众。它应该被编辑,或许更多地询问观众和各种格式,并更轻松地描述警告**尤其是95%** **我甚至不知道20%甚至5%符合该规则。 – 2011-05-17 20:16:19

+0

@George:默认情况下,我以全球观众为目标,但知道来自美国的人不会打扰。请注意,你会在美国找到这样的约翰斯和非约翰斯(即使大多数人像杜伊先生)。 – Gilles 2011-05-17 20:55:58

0

你想接受多少种不同的格式?

这里是一个应该为您发布的两项工作:

/(?<=((Mr\.|Mrs\.)\s+)?)([a-zA-Z]+)/ 
+0

只需将所有其他前缀添加到该列表中即可。 – 2011-05-17 19:48:13

+0

这不起作用。第一,并非所有(可能不是任何)版本的Perl都支持向后看内部的变量重复,并且第二,这将匹配Mr作为第一个名字。 – 2011-05-17 20:00:55

+0

这不适合我[http://regexr.com?2tpj3](http://regexr.com?2tpj3)。如何使用可选组工作来向后看?假设没有先生,那么它应该是空的,你的最后一部分将匹配任何单词,即使是最后一个名字。 – stema 2011-05-17 20:02:12

0

我认为这会工作

my $nameFull = 'Mr. John Doe'; 
my $nameFirst = $1 if $nameFull =~ /(?:\s|^)(?!(?:mr|mr?s|miss|dr|prof)(?![a-z]))([a-z]+)/i; 

解释:

/ ... /i开始和的结束不区分大小写的正则表达式

  • (?:\s|^)确保我们或者位于空白字符或字符串的开头。
  • (?! ...... )确保这不会匹配在第一个名称的开头
    • (?:mr|mr?s|miss|dr|prof)缩写列表(r?意味着可选r所以这将匹配MsMrs
    • (?![a-z])确保在缩写后面没有更多字母,因为drake是以dr开头的名称
  • ( ... )将其捕获到$1
    • [a-z]+连续出现多少个字母。假设至少有一个。
+0

我很抱歉,我现在测试了它,确实工作正常。我不明白在你的复杂正则表达式中你的lookaheads在这里发生了什么,但它在这个例子中提供了第一个名字。 – stema 2011-05-17 20:41:34

1

试试这一个,你的名字是第一个捕获组$1英寸

^(?:Mr\.|Mrs\.)?\s*\b([^\s]*)\b.*$ 

看到它online here on Regexr

+0

这应该工作。它还支持“约翰先生”。 – 2011-05-17 20:24:16

1

下面是一个简单的正则表达式将匹配这两种情况下

/^(?:\w+\.)?\s*(\w+).*$/ 
// $1 = John 

你可以建立起来这样的:
\w+\.至少一个单词字符后跟一个点(用于名称前缀)
(\w+\.)?该组可以出现一次或根本不出现
(?:\w+\.)?组非捕获(我们并不需要它)
^(?:\w+\.)? ^标志着整个字符串的开头(所以这个组是在它的第一件事) ^(?:\w+\.)?\s*这个前缀组可以跟任意数量的空格(或无)
^(?:\w+\.)?\s*(\w+)比遵循名称的组(其中包括至少一个字字符)
^(?:\w+\.)?\s*(\w+).*$终于.*字符的其他部分相匹配,直到字符串的结尾$

+0

聪明!带点的任何东西都是缩写! :) – 2011-05-17 20:23:58