我有一系列名称采用以下形式:
我努力寻找一个正则表达式,这将允许我将每个元素作为单独的文本元素提取。我的代码目前看起来如下:
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 ) )
此模式与第二个名称格式匹配,允许我提取其组成部分但与第一个不匹配(毫无疑问是由于前瞻)。当我向前看可选((.+?), (.+?) (.*)(?:, )?((.*))?$
)时,我匹配第一个名称格式,但是当我使用第二个名称格式时,我同时捕获中间名和后缀。我确信有一种简单的方法可以实现我的目标,但在正则表达式方面我相对缺乏经验。
提前感谢您的帮助!
答案 0 :(得分:1)
你的模式没有前瞻。 (?:pattern)
的模式称为非捕获组。它们就像常规匹配一样,除了它们允许您在括号中对东西进行分组而没有分配group(n)
个数字。这很好,因为你真的不需要为此目的进行前瞻。
您需要说的是逗号和后缀作为一个组是可选的。为此,请将逗号和后缀放在括号中(您可以在此处使用(?:
),并在整个组之后放置?
:
Pattern pattern = Pattern.compile("(.+?), (.+?) (.*)(?:, (.*))?$");
但是,这不会解决您的第二个问题,即第三个组(.*)
将消耗尽可能多的字符。由于最后一部分(逗号+后缀)是可选的,因此正则表达式发现它可以使用字符串的其余部分并仍然获得匹配。要解决此问题,您可以将其视为不情愿的匹配,就像您对前两组所做的那样:
Pattern pattern = Pattern.compile("(.+?), (.+?) (.*?)(?:, (.*))?$");
或者只是告诉(.*)
不要匹配任何逗号:
Pattern pattern = Pattern.compile("(.+?), (.+?) ([^,]*)(?:, (.*))?$");
注意:我还没有测试其中任何一个。