Как разделить строку по символу-якорю

У меня есть строка, допустим &atext1&btext2 &c- &{{#FFFFFF; #000000}}text3.
То, что идет после & - это цвет. Он может быть в формате &<символ> или &{{<hex через ;>}}.
Как я могу разделить текст в массив, что бы он выглядел примерно так: ["&a", "text1", "&b", "text2 ", "&c", "- ", "&{{#FFFFFF; #000000}}", "text3."]?


Ответы (1 шт):

Автор решения: Nowhere Man

Для разбиения по символу используется метод String::split, затем можно использовать обычные методы String::substring / String.lastIndexOf, чтобы определить пары, похожие на "ключ-значение":

String[] result = Arrays.stream(str.split("&"))
    .filter(s -> !s.isEmpty())
    .flatMap(s -> s.lastIndexOf("}") == -1 
        ? Stream.of(s.substring(0, 1), s.substring(1))
        : Stream.of(s.substring(0, s.lastIndexOf("}") + 1), s.substring(s.lastIndexOf("}") + 1))
    )
    .toArray(String[]::new);

System.out.println(Arrays.toString(result));
// -> [a, text1, b, text2 , c, - , {{#FFFFFF; #000000}}, text3.]

Или же можно определить регулярное выражение для каждой пары и использовать поток совпадений:
&([^}&]+\}\}|.)([^&]+):

  • & - начинается с символа &
  • группа 1: ([^}&]+\}\}|.) - непустая последовательность любых символов кроме } и &, ограниченная двумя закрывающими фигурными скобками ИЛИ один любой символ
  • группа 2: ([^&]+) - любые символы (хотя бы 1), кроме разделителя &
Pattern p = Pattern.compile("&([^}&]+\\}\\}|.)([^&]+)");
String[] result2 = p.matcher(str)
    .results() // Stream<MatchResult>
    .flatMap(mr -> Stream.of(mr.group(1), mr.group(2)))
    .toArray(String[]::new);
System.out.println(Arrays.toString(result2));
// -> [a, text1, b, text2 , c, - , {{#FFFFFF; #000000}}, text3.]

→ Ссылка