使用空格修剪字符串

3
我希望能够获得帮助,解析一个人名的字符串。我想要提取出这个字符串中的名字,只保留名字。

假设我有一个名字如下:

Mr. John Doe
John Smith.

在这两种情况下,我只想获得字符串的第一个名称并删除所有其他字符。
因此,在解析后,这两个字符串将只有John
我想知道是否有一种使用正则表达式解决此问题的方法。
5个回答

6

你不能这样做。除非你弄错了某些人的名字,让他们感到很不爽。你无法区分约翰·保罗·多(名字为“约翰”,中间名为“保罗”,姓为“多”),约翰·约瑟夫·布朗(回答“约瑟夫”或“乔”,但只在政府表格上使用“约翰”),以及约翰·保罗·史密斯(名字为“约翰·保罗”,讨厌缩写)。

去阅读程序员关于姓名的错误信念

然后再去读一遍,并接受这样一个事实:是的,世界上95%的人对名字的定义与你的完全不同。(如果你是中国人,则为80%。)

你最多只能截断空格和一些“安全”的前缀,例如“先生”——即使这些也不要删减(如果人们特意写上“先生”,他们可能希望在那里看到它)。

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

3
这篇文章夸大了问题,并假设原帖作者的观众是全球范围内的。相反,它应该被编辑以更多地询问读者群体和各种格式的差异,并且要更加温和地描述注意事项,特别是“尤其是95%”这一说法。我甚至不知道有20%或5%的情况符合这个规则。 - 700 Software
@George:默认情况下,我面向全球观众,但知道美国人不介意。请注意,在美国你会发现这样的约翰和非约翰(即使大多数人像多先生一样)。 - Gilles 'SO- stop being evil'

1

试试这个,你的名字在第一个捕获组 $1 中。

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

在Regexr上在线查看


1

这里有一个简单的正则表达式,可以匹配两种情况

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

你可以这样构建它:
\w+\. 至少一个单词字符后跟一个点(用于名称前缀)
(\w+\.)? 该组可以出现一次或不出现
(?:\w+\.)? 该组是非捕获的(我们不需要它)
^(?:\w+\.)? ^ 表示整个字符串的开头(因此该组是其中的第一件事) ^(?:\w+\.)?\s* 这个前缀组后面可以跟任意数量的空格(或没有)
^(?:\w+\.)?\s*(\w+) 然后是名称组(由至少一个单词字符组成)
^(?:\w+\.)?\s*(\w+).*$ 最后,.* 匹配其余的字符直到字符串的末尾 $


聪明!任何带点的东西都是缩写! :) - 700 Software

0
你想接受多少种不同的格式?
这是一个适用于你发布的两个格式的解决方案:
/(?<=((Mr\.|Mrs\.)\s+)?)([a-zA-Z]+)/

只需在列表中添加所有其他前缀。 - Mohamed Nuur
这样做行不通。首先,并非所有(也许没有任何一个)Perl版本都支持lookbehind内的变量重复,其次,这将匹配Mr作为名字的第一个单词。 - 700 Software
这对我不起作用http://regexr.com?2tpj3。你的可选组合回顾应该如何工作?假设没有先生,那么它应该是空的,你的最后一部分将匹配任何单词,甚至是姓氏。 - stema
@George,请问是否有任何版本的Perl可以支持变量长度的后顾断言?因为我现在只知道.net支持这个功能。 - stema
@stema:编辑了我的评论,我不想过于自信而犯错。 - 700 Software

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]+ 连续的字母。假设至少有一个。

很抱歉,我现在测试了一下,确实可以工作。我不明白你的复杂正则表达式和先行断言在这里发生了什么,但它在这个例子中提供了名字。 - stema

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接