Java Regex将化合物名称分组

时间:2017-06-25 11:03:21

标签: java regex

我正在创建一个在控制台上请求某些名称的java应用程序,然后使用正则表达式来提取没有逗号的名称,并且仅根据此表达式提取正确的名称:

(\\w{2,}(|\\s\\w{2,})+)

我在web正则表达式模拟器上检查了上面的表达式,似乎可以正常工作,但是当我尝试使用Pattern和Matcher Classes在Java上匹配它时,它对于以下名称不起作用: Alvaro de拉托雷

它将名称分为4组(在本例中)。我需要化合物名称只在一个字符串中。

我非常感谢任何帮助。提前谢谢。

3 个答案:

答案 0 :(得分:2)

我假设您要从" Alvaro de la Torre" 中提取" de la Torre" 等字符串。

使用正则表达式,捕获组2将以+重复,并且包含" de" 在第一次迭代中," la" 在第二次迭代中," Torre" 在第三次也是最后一次迭代。所以,当你最终从Matcher获得第2组时,它只包含"托瑞"

因此,您必须capture a repeated group

,而不是重复捕获组
"(\\w{2,}(|(\\s\\w{2,})+))"

请注意包含内部组和+的其他组。

现在,当你从Matcher获得第2组时,它包含内部组的所有重复,即" de la Torre"

Pattern pattern = Pattern.compile("(\\w{2,}(|(\\s\\w{2,})+))");
Matcher matcher = pattern.matcher("Alvaro de la Torre");
matcher.matches();
System.out.println(matcher.group(2));

打印" de la Torre"

上述正则表达式的更好的等效版本是:

"\\w{2,}((?:\\s\\w{2,})*)"

然后得到第1组而不是第2组。将整个正则表达式包装在捕获组中是没有意义的,因为整个匹配只是默认组0。

如果您只想从较大的字符串中提取" Alvaro de la Torre" 等全名,请使用matcher.find()代替{{1} },并获得匹配的子字符串matcher.matches()(获取默认组0,即匹配)。在这种情况下,您也不需要任何明确的捕获组。

答案 1 :(得分:0)

由于我们生活在一个确定性的世界中,机器遵循确定性规则。特别是,在正则表达式中,如果满足捕获组的第一个字段,则解析器将不会检查第二个字段,如果它不是绝对必要的话。

因此,由于嵌套捕获组((|\\s\\w{2,}))的第一个字段是空字符串,因此正则表达式对它感到满意,而不检查其他字段。这就是为什么它返回4个不同的结果而不是1的原因。

替代正则表达式是:

(\\w{2,}(\\s\\w{2,}|)+)

反转捕获组中2个字段的顺序。

等效的正则表达式是:

(\\w{2,}(\\s\\w{2,})*)

检查this demo vs this other one(由于突出原因,正则表达略有不同)。

答案 2 :(得分:0)

首先,您希望\w匹配多个字母,而不是数字0-9。所以像Jack is 23yrs old这样的字符串是完全匹配的。

其次,你的分组中有一个管道,如果试图带来可选的含义并且不是偶然的,那么它不是展示这种质量的好方法。什么是正确的方法?使用明确包含可选功能的明星*量词。

第三,\s表示不仅仅是Space \x20个字符。它匹配标签\t,换行符\n,回车符\r。所以像

这样的字符串
My name is
Jack

也是一个完整的匹配。

最后,如果您只需要返回完整匹配的字符串,则根本不需要捕获组:

(?i)[a-z]{2,}(?:[ ][a-z]{2,})*