Эта несколько тяжелая реализация, использующая Matcher.find
вместо split
, также будет работать, хотя к тому времени, когда вам придётся закодировать цикл for
для такой тривиальной задачи, вы также можете вообще отбросить регулярные выражения и использовать подстроки (для аналогичной сложности кодирования минус циклы процессора):
import java.util.*;
import java.util.regex.*;
public class StringSplit {
public static void main(String args[]) {
ArrayList<String> result = new ArrayList<String>();
for (Matcher m = Pattern.compile("..").matcher("12345"); m.find(result.isEmpty() ? 0 : m.start() + 1); result.add(m.group()));
System.out.println( result.toString() ); // prints "[12, 23, 34, 45]"
}
}
EDIT1
match()
: причина, по которой никто до сих пор не смог придумать регулярное выражение, подобное вашему BONUS_REGEX
, лежит в Matcher
, что возобновит поиск следующей группы, в которой закончилась предыдущая группа (т.е. без перекрытия) , как было предложено после того, с чего начиналась предыдущая группа, то есть, если явно не указывать начальную позицию поиска (см. выше). Хорошим кандидатом на BONUS_REGEX
был бы "(.\\G.|^..)"
, но, к сожалению, уловка \G
-anchor-in-the-middle не работает с Java Match
(но прекрасно работает в Perl):
perl -e 'while ("12345"=~/(^..|.\G.)/g) { print "$1\n" }'
12
23
34
45
split()
: что касается INSERT_REGEX_HERE
, хорошим кандидатом был бы (?<=..)(?=..)
(точка разделения - это позиция нулевой ширины, где у меня есть два символа справа и два слева), но опять же, потому что split
кончается ничем не перекрывающимся, в результате вы получите [12, 3, 45]
(что близко, но без сигары.)
EDIT2
Ради интереса, вы можете обмануть split()
, делая то, что вы хотите, сначала удваивая неограниченные символы (здесь вам нужно зарезервированное значение символа для разделения):
Pattern.compile("((?<=.).(?=.))").matcher("12345").replaceAll("$1#$1").split("#")
Мы можем быть умными и исключить необходимость в зарезервированном символе, воспользовавшись тем, что утверждения нулевой ширины упреждающие (в отличие от упреждающих) могут иметь неограниченную длину; поэтому мы можем разделить все точки, которые на равны четному количеству символов на расстоянии от конца удвоенной строки (и по крайней мере на два символа от ее начала), давая тот же результат, что и выше:
Pattern.compile("((?<=.).(?=.))").matcher("12345").replaceAll("$1$1").split("(?<=..)(?=(..)*$)")
В качестве альтернативы обманывает match()
аналогичным образом (но без необходимости в зарезервированном значении символа):
Matcher m = Pattern.compile("..").matcher(
Pattern.compile("((?<=.).(?=.))").matcher("12345").replaceAll("$1$1")
);
while (m.find()) {
System.out.println(m.group());
} // prints "12", "23", "34", "45"