Java - Извлечь строки с помощью Regex

У меня есть эта строка

String myString ="A~BC~FGH~~zuzy|XX~ 1234~ ~~ABC~01/01/2010 06:30~BCD~01/01/2011 07:45";

и мне нужно извлечь эти 3 подстроки
1234
6:30
7:45

Если я использую это регулярное выражение \\d {2} \:\\d {2}, я могу извлечь только первый час 06:30

Pattern depArrHours = Pattern.compile("\\d{2}\\:\\d{2}");
Matcher matcher = depArrHours.matcher(myString);
String firstHour = matcher.group(0);
String secondHour = matcher.group(1); (IndexOutOfBoundException no Group 1)

matcher.group(1) выдает исключение.
Также я не знаю, как извлечь 1234. Эта строка может измениться, но она всегда приходит после "XX ~"
Есть ли у вас какие-либо идеи о том, как сопоставить эти строки с выражениями регулярных выражений?

UPDATE

Благодаря предложению Адама у меня есть это регулярное выражение, которое соответствует моей строке

Pattern p = Pattern.compile(".*XX~ (\\d{3,4}).*(\\d{1,2}:\\d{2}).*(\\d{1,2}:\\d{2})";

Я сопоставляю число и 2 часа с matcher.group(1); matcher.group(2); matcher.group(3);

Ответы

Ответ 1

Функция matcher.group() ожидает принятия единственного целочисленного аргумента: индекс группы захвата, начиная с 1. Индекс 0 является специальным, что означает "все совпадение". Группа захвата создается с использованием пары скобок "(...)". Все, что находится в скобках, захватывает. Группы нумеруются слева направо (опять же, начиная с 1), открывая скобки (что означает, что группы могут перекрываться). Поскольку в вашем регулярном выражении нет скобок, не может быть группы 1.

javadoc в классе Pattern охватывает синтаксис регулярных выражений.

Если вы ищете шаблон, который может повторяться некоторое количество раз, вы можете использовать Matcher. find() несколько раз, пока он не вернется ложный. Matcher.group(0) один раз на каждой итерации будет возвращать то, что соответствовало этому времени.

Если вы хотите создать одно большое регулярное выражение, которое соответствует всем сразу (которое, как я считаю, вам нужно), то вокруг каждого из трех наборов вещей, которые вы хотите захватить, поместите набор захватывающих круглых скобок, используйте Matcher.match(), а затем Matcher.group(n), где n равно 1, 2 и 3 соответственно. Конечно, Matcher.match() может также возвращать false, и в этом случае шаблон не соответствует, и вы не можете получить какую-либо из групп.

В вашем примере то, что вы, вероятно, захотите сделать, это сопоставление с предыдущим текстом, затем запуск группы захвата, совпадение цифр, завершение группы захвата и т.д.... Я не знаю достаточно о вашем точном вводе формате, но вот пример.

Допустим, у меня были строки формы:

Eat 12 carrots at 12:30
Take 3 pills at 01:15

И я хотел извлечь количество и время. Мое регулярное выражение будет выглядеть примерно так:

"\w+ (\d+) [\w ]+ (\d{1,2}:\d{2})"

Код выглядит примерно так:

Pattern p = Pattern.compile("\\w+ (\\d+) [\\w ]+ (\\d{2}:\\d{2})");
Matcher m = p.matcher(oneline);
if(m.matches()) {
    System.out.println("The quantity is " + m.group(1));
    System.out.println("The time is " + m.group(2));
}

Регулярное выражение означает "строка, содержащая слово, пробел, одну или несколько цифр (которые фиксируются в группе 1), пробел, набор слов и пробелов, заканчивающихся пробелом, за которым следует время (захваченное в группе 2, и время предполагает, что час всегда 0-дополняется до 2-х цифр). Я приведу более подробный пример того, что вы ищете, но описание возможного ввода немного расплывчато.