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

时间:2013-05-10 15:27:27

标签: java regex string split

假设:

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]

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

4 个答案:

答案 0 :(得分:77)

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

而是将PatternMatcher类与\w+\s+\w+这样的正则表达式一起使用,除了更安全之外,还可以避免继承此类代码的人的维护地狱(请记住&#34 ; 总是编码,好像最终维护你的代码的人是一个知道你住在哪里的暴力精神病患者")。


这是你在找什么?
(您可以将\\w替换为\\S以包含所有非空格字符,但对于此示例,我将离开\\w,因为使用{更容易阅读正则表达式{1}}然后\\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)我们正在尝试

  1. 查找空格 - &gt; split
  2. 未预测 - &gt; \\s
  3. 通过某些词 - &gt; (?<!negativeLookBehind)
  4. 以前匹配(空格) - &gt; \\w+
  5. 之前 - &gt; \\G
  6. 我开始时只有混乱,因为我们希望忽略这个空间,它对第一个空间有什么作用。 重要信息是,\\G\\w+在开始时匹配字符串\\G 的开头。

    所以在第一次迭代之前,负面后卫的正则表达式看起来像^,并且由于第一个空格之前有(?<!^\\w+),所以它不匹配分裂。下一个空格不会有这个问题,因此它将被匹配,并且有关它的信息(如^\\w+字符串中的 位置 )将存储在{{1然后在下一个负面的后卫中使用。

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


    此外,如果有人愿意将每个第3个空格分开,您可以使用此表单(基于@maybeWeCouldStealAVan&#39; s answer,当我发布此答案片段时已删除了该表单

    \\G

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


    我刚注意到,如果我们想要像每隔3,5,7这样的每个奇数进行分割,我们也可以使用input代替input.split("(?<=\\G\\w{1,100}\\s\\w{1,100}\\s\\w{1,100})\\s")

    +

答案 1 :(得分: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));

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

答案 2 :(得分:0)

这对我有用(\w+\s*){2}\K\s 例如here

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

答案 3 :(得分:-1)

你可以试试这个:

[a-z]+\s[a-z]+

<强>更新

([a-z]+\s[a-z]+)|[a-z]+

enter image description here

<强>更新

 String pattern = "([a-z]+\\s[a-z]+)|[a-z]+";
 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 + "\"");