Как повторять выражение регулярного выражения
Скажем, у меня есть следующая строка:
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));
}
Есть ли способ сделать это с помощью одного регулярного выражения?
Ответы
Ответ 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