使用Perl正则表达式解析名称

时间:2012-02-24 16:08:31

标签: regex perl

尝试编写可以解析全名并将其拆分为名字,中间名,姓氏的正则表达式。这应该很简单但是一旦你看到我要解析的那种名字就很难了。现在我可以编写一个很长的正则表达式来考虑所有这些不同的情况,但我认为一个较小的动态正则表达式是可能的,这就是为什么我在这里寻求一些帮助。

我认为这些都是我必须抓住的所有类型的名字。

需要解析的一些示例名称(最后每个都有三个逗号):

(first name) (middle intial). (last name),,, //one middle initial with period after
(first name) (last name),,,                  //simple first and last
(No name),,,                                 //no name
(first name) (last name)-(last name),,,      //two last names separated by a dash
(first name) (middle initial). (middle initial). (last name),,,   //two middle initials with space inbetween
(first name) (last name w/ apostrophe),,,    //Last names with apostrophes 
(first name) (Middle name) (Last name),,,    //first middle and last name

3 个答案:

答案 0 :(得分:4)

你无法解析最终没有规则的东西,希望取得任何成功。问题不是将算法转换为正则表达式,而是将算法编写为开始。

考虑一下:您如何编写一个能够将所有这些名称正确解析为Given,Middle和Family名称的算法?

  • Bob Mac Intosh
  • Mary Jane Watson
  • 瑟斯顿鲍威尔三世
  • Michael van der Velden
  • Jacqueline Kennedy Onassis
  • 博士。让·格雷
  • Takahashi Shiro
  • Michel La Fontaine
  • Sir Alec Guinness
  • Mary-Sue Bowes-Lyon
  • Sacha Baron Cohen
  • Jack Arnold Jr。

明白我的意思?你需要一个AI才能将这些单词中的每个单词正确地组合到适当的上下文中。有些人使用两个名字作为“给定”名称。有些人使用头衔或敬意,有些文化将他们的姓氏放在第一位,最后给出了名字。

总结:不要这样做。如果您无法让用户将其名称分隔为特定的块,则必须将它们视为原子。

答案 1 :(得分:3)

use 5.010;
use DDS;
for (<DATA>) {
    chomp;
    s/,,,.*//;
    if (' ' eq $_) {
        say 'no name';
    } else {
        /\A (?<first>\S+) \s+ (?<middle>.*?)? (?:\s+)? (?<last>\S+) \z/msx;
        DumpLex \%+;
    }
}

__DATA__
Foo B. Baz,,,
Fnord Quux,,,
 ,,,
Xyzzy Bling-Bling,,,
Abe C. D. Efg,,,
Ed O'postrophe,,,
First Middle Last,,,

$HASH1 = {
           first  => 'Foo',
           last   => 'Baz',
           middle => 'B.'
         };
$HASH1 = {
           first  => 'Fnord',
           last   => 'Quux',
           middle => ''
         };
no name
$HASH1 = {
           first  => 'Xyzzy',
           last   => 'Bling-Bling',
           middle => ''
         };
$HASH1 = {
           first  => 'Abe',
           last   => 'Efg',
           middle => 'C. D.'
         };
$HASH1 = {
           first  => 'Ed',
           last   => 'O\'postrophe',
           middle => ''
         };
$HASH1 = {
           first  => 'First',
           last   => 'Last',
           middle => 'Middle'
         };

答案 2 :(得分:3)

没有代码,但请尝试:

  1. 使用substr删除$ name,
  2. 中的最后三个字符
  3. @array = split /[\s+.]+/, $ name#split in space和/或dots(如上所述)成一个数组,
  4. if($ array [0])那么你有 a 名称,
  5. $ lastname = pop @array; #获取最后(或唯一)名称
  6. $ firstname = shift @array if scalar @array; #first name是第一个元素
  7. @array现在包含所有中间名和/或首字母
  8. 总之那样......