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

2022-08-31 17:17:31

鉴于:

String input = "one two three four five six seven";

有没有一个正则表达式与String.split()一起使用,一次抓取(最多)两个单词,这样:

String[] pairs = input.split("some regex");
System.out.println(Arrays.toString(pairs));

结果是:

[one two, three four, five six, seven]

这个问题是关于拆分正则表达式的。它不是关于“找到一个解决方法”或其他“让它以另一种方式工作”的解决方案。


答案 1

目前(最后一次在Java 17上测试),可以使用split()来做到这一点,但在现实世界中不要使用这种方法,因为它看起来像是基于bug的,因为Java中的look-behind应该具有明显的最大长度,但是这个解决方案使用\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));

输出:

[one two, three four, five six, seven]

\G是前一场比赛,是负面的。(?<!regex)

在我们试图split

  1. 查找空间 ->\\s
  2. 未预测的 ->(?<!negativeLookBehind)
  3. 通过一些词->\\w+
  4. 具有先前匹配的(空格)->\\G
  5. 在它之前->。\\G\\w+

我一开始唯一感到困惑的是,它如何适用于第一个空间,因为我们希望忽略该空间。重要信息是 \\G 在开始时匹配字符串 ^ 的开始

因此,在第一次迭代之前,负向后看的正则表达式将看起来像这样,并且由于第一个空间之前确实有过,因此无法匹配拆分。下一个空间不会有这个问题,因此它将被匹配,有关它的信息(如它在String中的位置)将被存储并在下一个负面的后面使用。(?<!^\\w+)^\\w+input\\G

因此,对于第三个空格,正则表达式将检查之前是否有匹配的空格和单词。由于此测试的结果为正数,因此负向后看不会接受它,因此此空间将不匹配,但是第 4 个空间不会出现此问题,因为它之前的空间将与存储在 中的空间不同(它在 String 中的位置不同)。\\G\\w+\\Ginput


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

input.split("(?<=\\G\\w{1,100}\\s\\w{1,100}\\s\\w{1,100})\\s")

您可以使用一些较大的值来代替100,该值至少是String中最长单词的长度大小。


我刚刚注意到,我们也可以使用而不是我们想要拆分每个奇数,例如每个3rd,5th,7th。+{1,maxWordLength}

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 

答案 2

这将起作用,但需要提前设置最大字长:

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));

我更喜欢Pshemo的答案,更短,可以在任意单词长度上使用,但这(正如@Pshemo指出的那样)具有适应超过2个单词的组的优点。