使用java regex重新排序名称

时间:2014-08-10 03:41:29

标签: java regex lookahead

我有一系列名称采用以下形式:

  1. 史密斯,约翰沃尔特
  2. Jones,James Samuel,Jr。
  3. 我努力寻找一个正则表达式,这将允许我将每个元素作为单独的文本元素提取。我的代码目前看起来如下:

    Pattern pattern = Pattern.compile("(.+?), (.+?) (.*)(?:, )((.*))?$");
    Matcher matcher = pattern.matcher( name2 );
    
    System.out.println( matcher.find() );     
    System.out.println( matcher.groupCount() );
    System.out.println( matcher.group( 1 ) );  
    System.out.println( matcher.group( 2 ) );  
    System.out.println( matcher.group( 3 ) );  
    System.out.println( matcher.group( 4 ) )
    

    此模式与第二个名称格式匹配,允许我提取其组成部分但与第一个不匹配(毫无疑问是由于前瞻)。当我向前看可选((.+?), (.+?) (.*)(?:, )?((.*))?$)时,我匹配第一个名称格式,但是当我使用第二个名称格式时,我同时捕获中间名和后缀。我确信有一种简单的方法可以实现我的目标,但在正则表达式方面我相对缺乏经验。

    提前感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

你的模式没有前瞻。 (?:pattern)的模式称为非捕获组。它们就像常规匹配一样,除了它们允许您在括号中对东西进行分组而没有分配group(n)个数字。这很好,因为你真的不需要为此目的进行前瞻。

您需要说的是逗号和后缀作为一个组是可选的。为此,请将逗号和后缀放在括号中(您可以在此处使用(?:),并在整个组之后放置?

Pattern pattern = Pattern.compile("(.+?), (.+?) (.*)(?:, (.*))?$");

但是,这不会解决您的第二个问题,即第三个组(.*)将消耗尽可能多的字符。由于最后一部分(逗号+后缀)是可选的,因此正则表达式发现它可以使用字符串的其余部分并仍然获得匹配。要解决此问题,您可以将其视为不情愿的匹配,就像您对前两组所做的那样:

Pattern pattern = Pattern.compile("(.+?), (.+?) (.*?)(?:, (.*))?$");

或者只是告诉(.*)不要匹配任何逗号:

Pattern pattern = Pattern.compile("(.+?), (.+?) ([^,]*)(?:, (.*))?$");

注意:我还没有测试其中任何一个。