Я ищу регулярное выражение, которое соответствует простой пользовательской схеме номеров версий, которая состоит из неограниченного количества серий цифр, разделенных одиночными периодами, со следующими ограничениями:
Сопоставьте одну строку, указав позиции в начале и конце строки с помощью токенов ^
и $
.Поскольку номер версии представляет собой одну строку, не имеет смысла выполнять многострочное сопоставление.
Запрещается использование букв, пробелов или специальных символов.
Строка не может начинаться или заканчиваться точкой, и после начального номера каждой следующей серии цифр должен предшествовать один период.
Как упоминалось ранее, следует предположить, что данная схема может иметь неограниченное количество категорий, поэтому регулярное выражение должно иметь возможность захватывать неограниченное количество групп, каждая из которых представляет уникальную категорию версии.
Пример схемы
<MajorVersion>.<MinorVersion>.<BuildNumber>
Захваченные группы
$1 = MajorVersion, $2 = MinorVersion, $3 = BuildNumber
Вышеприведенный пример можно перевести в реальный пример:
Version number: 0.1.2 = [ $1 = 0, $2 = 1, $3 = 2 }
Тестовые случаи
Should pass - 010.98
Captured groups = { $1 = 010, $2 = 98 }
Should pass - 0.12.3344.2.1
Captured groups = { $1 = 0, $2 = 12, $3 = 3344, $4 = 2, $5 = 1 }
Should fail - 0 23.42 // Contains white-spaces
Should fail - 1.2..3.4 // Contains consecutive period symbols
Should fail - .2.58.6 // Starts with a period symbol
Should fail - 64#23.4 // Contains special characters
Текущее решение
Я пытаюсь реализовать решение синтаксического анализа на Java и не доволен моим текущим решением, которое требует от меня дважды проанализировать номер данной версии String
:
- Один раз для проверки того, что
String
является действительным номером версии, который соответствует ограничениям, перечисленным выше, с использованием следующего регулярного выражения:
^\d+(?:\.\d+)*$
- Один раз для захвата каждой серии цифр в виде отдельной категории версий с использованием положительного взгляда с использованием следующего регулярного выражения:
(?<=^|\.)\d+
Для тех, кто заинтересован в предоставлении решения Java, вот кодИспользую для тестирования:
public static final Pattern SIMPLE_VERSION_NUMBER_MATCH = Pattern.compile("^\\d{1}(?:\\.\\d)*$");
public static final Pattern SIMPLE_VERSION_NUMBER_GROUPS = Pattern.compile("(?<=^|\\.)\\d+");
@Test
public void testRegExMathCollection() {
String versionNumber = "0.1.2.3";
Assertions.assertTrue(RegExPatterns.SIMPLE_VERSION_NUMBER_MATCH.matcher(versionNumber).find());
assertPatternMatchesGroups(RegExPatterns.SIMPLE_VERSION_NUMBER_GROUPS, versionNumber, "0", "1", "2", "3");
}
@TestOnly
private void assertPatternMatchesGroups(Pattern pattern, String text, String... groups) {
String[] matches = RegExUtils.collectMatches(pattern.matcher(text));
Assertions.assertArrayEquals(groups, matches);
}
public static String[] collectMatches(Matcher matcher) {
List<String> matches = new java.util.ArrayList<>();
while (matcher.find()) {
matches.add(matcher.group());
}
return matches.toArray(new String[0]);
}
Сегмент вопроса
Мой вопрос к вам двоякий:
- Как лучше всего решить эту проблемуиспользуя Single обычный эксpression?
- Если вышеприведенное невозможно, есть ли более оптимальные модели, чем те, которые я сейчас использую?
- Если, по вашему мнению, регулярное выражение не лучший подход, какую реализацию Java вы бы порекомендовали для решения этой проблемы?
Редактировать: Обратите внимание, что это в первую очередьвопрос о регулярных выражениях в качестве основной цели состоит в том, чтобы получить одно регулярное выражение, способное как проверять номер версии в соответствии с приведенными выше ограничениями, так и группы захвата.Я только попросил лучшее решение Java в качестве запасного варианта на случай, если то, что я хочу, невозможно сделать с помощью регулярных выражений.