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

鉴于:

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

是否有一个正则expression式可以与String.split()一起抓取(最多)两个单词,例如:

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

结果如下:

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

这个问题是关于分裂正则expression式 。 这不是 “寻找解决办法”或其他“以另一种方式工作”的解决scheme。

目前(包括Java 8)可以使用split() ,但在现实世界中不要使用这种方法,因为它看起来像是基于bug(Java中的后台应该有明显的最大长度,但是这个解决scheme使用\w+不尊重这个限制)。 相反,使用PatternMatcher类来避免过度繁杂和维护地狱,因为这种行为可能在Java的下一个版本或像Java这样的Java环境中发生变化。


这是你想要的?
(你可以用\\Sreplace\\w以包含所有非空格字符,但是对于这个例子我将离开\\w因为用\\w\\s来读取正则expression式更容易\\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. find空格 – > \\s
  2. 没有预测 – > (?<!negativeLookBehind)
  3. 通过一些单词 – > \\w+
  4. 与先前匹配(空间) – > \\G
  5. 在它之前 – > \\G\\w+

只有我一开始就感到困惑,因为我们希望这个空间被忽略,它对于第一空间将会如何工作。 重要的信息是\\G在开始比赛开始string^

所以在第一次迭代之前,负面后视中的正则expression式看起来像(?<!^\\w+)并且由于第一个空间之前有^\\w+ ,所以它不能匹配分割。 下一个空间不会有这个问题,所以它会被匹配,并且关于它的信息(比如它在inputstring中的位置 )将被存储在\\G并在以后的负面后续处理中使用。

因此,对于第三空间,正则expression式将检查之前是否有先前匹配的空间\\G和word \\w+ 。 由于这个testing的结果是肯定的,所以负面的后视不会接受它,所以这个空间不会被匹配,但是第四空间不会有这个问题,因为它之前的空间不会像存储在\\G (它将有不同的位置在inputstring)。


此外,如果有人想分开让我们说每隔三个空间,你可以使用这种forms(基于@maybeWeCouldStealAVan的答案 ,当我发布这个答案的片段时被删除)

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

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


我只是注意到,如果我们想要每隔{1,maxWordLength}每一个奇数分割,我们也可以使用+而不是{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 

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

 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个以上单词组的优点。

这工作对我来说(\w+\s*){2}\K\s 这里 (\w+\s*){2}\K\s例子

  • 一个必需的单词后跟一个可选的空格(\w+\s*)
  • 重复两次{2}
  • 忽略以前匹配的字符\K
  • 所需空间\s

你可以试试这个:

 [az]+\s[az]+ 

更新:

 ([az]+\s[az]+)|[az]+ 

在这里输入图像描述

更新:

  String pattern = "([az]+\\s[az]+)|[az]+"; String input = "one two three four five six seven"; Pattern splitter = Pattern.compile(pattern); String[] results = splitter.split(input); for (String pair : results) { System.out.println("Output = \"" + pair + "\"");