Java正则表达式对复合名称进行分组

Java正则表达式对复合名称进行分组,java,regex,Java,Regex,我正在创建一个java应用程序,该应用程序在控制台上请求一些名称,然后使用正则表达式仅提取不带逗号的名称,并且仅提取符合以下表达式的正确名称: (\\w{2,}(\\s\\w{2,})+ 我在一个web正则表达式模拟器上检查了上述表达式,似乎可以满足我的要求,但当我尝试在Java上使用模式和匹配器类来匹配它时,它对诸如:Alvaro de la Torre之类的名称就不起作用了 它将名称分成4个组(在本例中)。我需要复合名称仅在一个字符串中 我将非常感谢任何帮助。提前感谢。因为我们生活在一个确定

我正在创建一个java应用程序,该应用程序在控制台上请求一些名称,然后使用正则表达式仅提取不带逗号的名称,并且仅提取符合以下表达式的正确名称:

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

我在一个web正则表达式模拟器上检查了上述表达式,似乎可以满足我的要求,但当我尝试在Java上使用模式和匹配器类来匹配它时,它对诸如:Alvaro de la Torre之类的名称就不起作用了

它将名称分成4个组(在本例中)。我需要复合名称仅在一个字符串中


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

因为我们生活在一个确定性的世界中,机器遵循确定性规则。特别是,在正则表达式中,如果满足捕获组的第一个字段,解析器将不会检查第二个字段(如果严格来说不需要)

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

另一种正则表达式是:

(\\w{2,}(\\s\\w{2,}|)+)
(\\w{2,}(\\s\\w{2,})*)
"\\w{2,}((?:\\s\\w{2,})*)"
这将反转捕获组中2个字段的顺序

等效正则表达式是:

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

检查vs(由于突出显示的原因,正则表达式略有不同)。

首先,您想知道
\w
匹配的不仅仅是字母,比如数字
0-9
。所以像杰克23岁这样的字符串是完全匹配的

第二,在你的分组中有一个管道,如果它试图带来可选的含义,而不是偶然出现的,那么它不是展示这种质量的好方法。正确的方法是什么?使用星号
*
量词,该量词基本上包含可选功能

第三,
\s
不仅仅意味着一个字符。它匹配制表符
\t
、换行符
\n
、回车符
\r
。那么一条像

My name is
Jack
这也是一场完整的比赛

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

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

我假设您想从的“Alvaro de la Torre”中提取一个字符串,如“de la Torre”

使用正则表达式,捕获组2以
+
重复,在第一次迭代中包含“de”,在第二次迭代中包含“la”,在第三次和最后一次迭代中包含“Torre”。因此,当您最终从
匹配器中获得第2组时,它只包含“Torre”

因此,与重复捕获组不同,您必须:

请注意包含内部组和
+
的附加组

现在,当您从
匹配器中获得第2组时,它包含内部组的所有重复,即“德拉托瑞”

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));
打印“德拉托瑞”


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

(\\w{2,}(\\s\\w{2,}|)+)
(\\w{2,}(\\s\\w{2,})*)
"\\w{2,}((?:\\s\\w{2,})*)"
然后得到第1组而不是第2组。将整个正则表达式包装在捕获组中是没有意义的,因为整个匹配只是默认的组0



如果您只想从较大的字符串中提取全名,如“Alvaro de la Torre”,则只需使用
matcher.find()
,而不是
matcher.matches()
,并使用
matcher.group()
获取匹配的子字符串(即默认组0)。在这种情况下,您也不需要任何明确的捕获组。

嘿,David,一条建议:具有正则表达式知识的人可能很容易理解,但一般来说,您应该提供输入、实际输出和所需输出的示例。我认为正则表达式中的管道是罪魁祸首。把它拿走。