如何使用Regex解析自定义版本号方案?

时间:2019-06-29 22:08:05

标签: java regex

我正在寻找一个正则表达式,该正则表达式将与一个简单的自定义版本编号方案相匹配,该方案由一个无限数量的数字组成,这些数字在以下约束下由单个句点分隔:

  • 通过使用^$标记在行的开头和结尾声明位置来匹配一行。由于版本号是单行,因此没有必要进行多行匹配。

  • 不允许使用字母,空格或特殊字符。

  • 该行不能以句点开头或结尾,并且在初始数字之后,每个随后的数字序列必须以一个句点开头。

如前所述,应该假定给定方案可以具有无限数量的类别,因此正则表达式应该能够捕获无限数量的组,每个组代表一个唯一的版本类别。

方案示例

<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]);
}

问题细分

我对您的问题有两个:

  • 使用单个正则表达式解决此问题的最佳方法是什么?
  • 如果上述方法不可行,那么是否有比我目前正在使用的最优模式更多的最优模式?
  • 如果您认为正则表达式不是最好的方法,那么您将建议使用哪种Java实现来解决此问题?

编辑:请注意,这主要是关于正则表达式的问题,因为主要目的是获得一个能够同时根据以下要求验证版本号的正则表达式上面提供的约束以及捕获组。我只是要求一个更好的Java解决方案作为后备,以防万一我无法使用正则表达式。

2 个答案:

答案 0 :(得分:2)

使用"1.2.3.4.5".split("\\."),查看链接的其他问题。

当您需要在较大的字符串中查找模式时,或者在需要检查字符串是否具有必需的格式时,或者当字符串包含要忽略的其他字符时,使用正则表达式会更有用。

如果您知道所有输入的格式正确,则regex不能提供比简单拆分更优越的功能。

答案 1 :(得分:1)

我认为您可以使用此正则表达式:\ d +。\ d +。\ d +

如果它不起作用,您是否还有更多示例可以对其进行测试?