按字符计数或非单词字符的最后一个索引拆分

时间:2017-02-27 16:58:15

标签: java regex

我有这样的字符串:

aaaaaas#aa##aa

我想用split()和正则表达式来完成这个算法:

  • 获得5个第一个字符
  • 如果它有一些非单词字符,则剪切为最后一个非单词字符,包括非单词字符
  • 如果它没有任何非单词字符,则剪切此5个字符
  • 从最后一次切割重复直到字符串结束

此示例的返回应如下所示:

aaaaa
as#
aa##
aa

甚至可以使用正则表达式和split()?此

.*([\W]+)\W

为我提供了最后一个非单词字符的字符(例如,它将是aaaaaas#aa##)但是如何将其分组为最大字符。 5个字符,从上一场比赛结束后拆分并继续?

https://regex101.com/r/xA9kG3/14

1 个答案:

答案 0 :(得分:2)

  

甚至可以使用正则表达式和split()

是的,但完全实现您描述的内容非常麻烦。请特别注意,您的规范表征了您想要接受的子字符串,而split()则用于匹配子字符串之间的分隔符

但是,你可以通过对分隔符模式使用零宽度的外观断言来做这种事情,但结果需要一个冗长而丑陋的正则表达式来准确地实现您的特定要求。最重要的是,5个字符的窗口会让事情变得一团糟。 Java正则表达式支持特殊\G以匹配上一个匹配的尾随边界(如果有),这使得作业成为可能

这是我提出的最佳模式:

(?x) (?<= \\G\\w{5} )
   | (?<= \\G  .{4} \\W )
   | (?<= \\G  .{3} \\W ) (?= \\w )
   | (?<= \\G  .{2} \\W ) (?= \\w{2} | \\w\\z )
   | (?<= \\G  .    \\W ) (?= \\w{3} | \\w{1,2}\\z )
   | (?<= \\G       \\W ) (?= \\w{4} | \\w{1,3}\\z )

(注意,启用了注释模式,使模式中的空格无效。)

自上次匹配以来,有五个单词字符隐式跟随分隔符,并且对于以非单词字符结尾的标记,每个可能的标记长度都有一个。我顺便观察到,在这种情况下,分隔符不一定落在第一个非单词/单词边界,也不一定在这样的边界处,而是在所考虑的一次五个最后一个非单词字符之后。此外,在最后一个令牌之后不需要存在分隔符。