使用String.split()提取单词对

Boh*_*ian 55 java regex string split

鉴于:

String input = "one two three four five six seven";
Run Code Online (Sandbox Code Playgroud)

是否有一个正则表达式,一次String.split()抓取(最多)两个单词,这样:

String[] pairs = input.split("some regex");
System.out.println(Arrays.toString(pairs));
Run Code Online (Sandbox Code Playgroud)

结果如下:

[one two, three four, five six, seven]
Run Code Online (Sandbox Code Playgroud)

这个问题是关于分裂正则表达式.它不是 "找到一种解决方法"或其他"使其以另一种方式工作"的解决方案.

Psh*_*emo 78

目前(包括Java 10)可以使用它split(),但在现实世界中不要使用这种方法,因为它看起来像是基于bug,因为Java中的后视应该有明显的最大长度,但是这个解决方案使用\w+哪个不尊重这个限制,并以某种方式仍然有效 - 所以如果它是一个将在以后的版本中修复的错误,这个解决方案将停止工作.

相反,使用PatternMatcher教学班,正则表达式像\w+\s+\w+被更安全的这一边也避免了维护地狱的人谁将会继承这样的代码(记得要" 始终代码,如果谁最终维护你代码的人是暴力变态谁知道你住在哪里 ") .


这是你想要的?
(您可以替换\\w\\S包括所有非空格字符,但在这个例子中,我会离开\\w,因为它是更容易阅读正则表达式\\w\\s,然后\\S\\s)

String input = "one two three four five six seven";
String[] pairs = input.split("(?<!\\G\\w+)\\s");
System.out.println(Arrays.toString(pairs));
Run Code Online (Sandbox Code Playgroud)

输出:

[one two, three four, five six, seven]
Run Code Online (Sandbox Code Playgroud)

\G是以前的比赛,(?<!regex)是负面的背后.

split我们试图

  1. 找到空格 - > \\s
  2. 那是没有预测的 - > (?<!negativeLookBehind)
  3. 用一些词 - > \\w+
  4. 以前匹配(空格) - > \\G
  5. 在它之前 - > \\G\\w+.

我开始时只有混乱,因为我们希望忽略这个空间,它对第一个空间的效果如何.重要信息是\\G在开始时匹配String的开始^.

因此,在第一次迭代之前,负面后视中的正则表达式看起来像是(?<!^\\w+)因为之前的第一个空间确实存在^\\w+,所以它不能与split进行匹配.下一个空格不会出现这个问题,因此它将被匹配,关于它的信息(如它在String中的位置input)将被存储\\G并在下一个负面的后视中使用.

因此对于第三空间,正则表达式将检查之前是否存在先前匹配的空格\\G和单词\\w+.由于本次测试的结果将是积极的,消极的样子,后面不会接受它,所以这个空间不会被匹配,但第四空间不会有这个问题,因为空间之前,它不会与存储在\\G(它会在不同的位置input字符串) .


此外,如果有人想要分开,可以说每隔3个空格就可以使用这个表格(基于@maybeWeCouldStealAVan答案,当我发布这个答案的片段时被删除)

input.split("(?<=\\G\\w{1,100}\\s\\w{1,100}\\s\\w{1,100})\\s")
Run Code Online (Sandbox Code Playgroud)

而不是100,你可以使用一些更大的值,至少是String中最长单词长度的大小.


我只是注意到我们也可以使用+而不是{1,maxWordLength}如果我们想要像每个第3,第5,第7那样分割每个奇数

String data = "0,0,1,2,4,5,3,4,6,1,3,3,4,5,1,1";
String[] array = data.split("(?<=\\G\\d+,\\d+,\\d+,\\d+,\\d+),");//every 5th comma 
Run Code Online (Sandbox Code Playgroud)


may*_*Van 9

这将有效,但需要提前设置最大字长:

String input = "one two three four five six seven eight nine ten eleven";
String[] pairs = input.split("(?<=\\G\\S{1,30}\\s\\S{1,30})\\s");
System.out.println(Arrays.toString(pairs));
Run Code Online (Sandbox Code Playgroud)

我更喜欢Pshemo的答案,更短,可用于任意字长,但这(如@Pshemo所指出的)具有适应超过2个字的组的优点.

  • 答案为+1,可轻松适应任意数量的应分组的单词. (2认同)