Подтвердить что ты не робот

Как повторять выражение регулярного выражения

Скажем, у меня есть следующая строка:

name1=gil;name2=orit;

Я хочу найти все совпадения name=value и убедиться, что вся строка соответствует шаблону.

Итак, я сделал следующее:

  • Убедитесь, что весь шаблон соответствует желаемому.

    Pattern p = Pattern.compile("^((\\w+)=(\\w+);)*$");
    Matcher m = p.matcher(line);
    if (!m.matches()) {
        return false;
    }
    
  • Итерации по шаблону name=value

    Pattern p = Pattern.compile("(\\w+)=(\\w+);");
    Matcher m = p.matcher(line);
    while (m.find()) {
        map.put(m.group(1), m.group(2));
    }
    

Есть ли способ сделать это с помощью одного регулярного выражения?

4b9b3361

Ответ 1

Вы можете проверить и перебрать совпадения с одним регулярным выражением с помощью:

  • Обеспечение отсутствия совпадающих символов между совпадениями (например, name1=x;;name2=y;), поместив \G в начало нашего регулярного выражения, что означает "конец предыдущего матча" .

  • Проверка того, достигли ли мы конца строки в нашем последнем совпадении, сравнивая длину нашей строки с Matcher.end(), который возвращает смещение после сопоставления последнего символа.

Что-то вроде:

String line = "name1=gil;name2=orit;";
Pattern p = Pattern.compile("\\G(\\w+)=(\\w+);");
Matcher m = p.matcher(line);
int lastMatchPos = 0;
while (m.find()) {
   System.out.println(m.group(1));
   System.out.println(m.group(2));
   lastMatchPos = m.end();
}
if (lastMatchPos != line.length())
   System.out.println("Invalid string!");

Живая демонстрация.


Некоторые языки могут позволить вам выполнять итерацию по отдельным матчам непосредственно из
^((\\w+)=(\\w+);)*$, но я не думаю, что вы можете сделать это на Java.

Ответ 2

Вы должны включить многострочный режим для "^" и "$" для работы, как ожидалось.

Pattern p = Pattern.compile("^(?:(\\w+)=(\\w+);)*$", Pattern.MULTILINE);
while (m.find()) {
    for (int i = 0; i < m.groupCount() - 2; i += 2) {
        map.put(m.group(i + 1), m.group(i + 2));
    }
}

Комментарии, где правильно, вам все равно придется перебирать сопоставимые группы для каждой строки и сделать внешнюю группу не захватывающей группой (?:...).

Ответ 3

String example = "name1=gil;name2=orit;";
Pattern pattern = Pattern.compile("((name[0-9]+?=(.+?);))+?");
Matcher matcher = pattern.matcher(example);
// verifies full match
if (matcher.matches()) {
    System.out.println("Whole String matched: " + matcher.group());
    // resets matcher
    matcher.reset();
    // iterates over found
    while (matcher.find()) {
        System.out.println("\tFound: " + matcher.group(2));
        System.out.println("\t--> name is: " + matcher.group(3));
    }
}

Выход:

Whole String matched: name1=gil;name2=orit;
    Found: name1=gil;
    --> name is: gil
    Found: name2=orit;
    --> name is: orit