Home > database >  Java regular expression to match specific integer values separated by a dot delimiter
Java regular expression to match specific integer values separated by a dot delimiter

Time:11-03

Basically I'm trying to implement three regular expressions as specified below -

  1. First regular expression should match at the least the literal string 10.1 or any string like 10.1.0.0 or 10.1.1.0 or 10.2.1.0 or 10.2.1.1 and so on but it should at the least match 10.1 or any higher versions. I tried the following regular expression \d \.\d (\.\d \.\d )* but this matches even lower versions such as 9.1.1.0 or 9.1 and so on.

  2. Second regular expression should match anything higher than the string literal 10.1 but not 10.1 but it should match any other string like 10.2 or 10.3 or 10.1.0.0 or 10.1.1.0 or 10.2.1.0 or 10.2.1.1 or 10.2 or 10.3 or 11.1.1.0 or 11.1 and so on. Tried the following but did not match the expectation (\\d )\\.(\\d )(.*)

  3. Third regular expression should match anything lower than the string literal 10.1 but not 10.1 but it should match any other string like 10.0 or 9.1 or 9.2 or 9.1.1.0 or 9.1 or 9.1.2.0.

Basically how do I match the literal string like 10.1 followed by any optional numbers separated by a dot and how do I match anything higher or lower than the literal string like in my 1st, 2nd and 3rd points?

I'm still trying to modify my regular expression to match my requirement, any help/guidance will be very helpful.

CodePudding user response:

Not really feasible as "4" < "10" and such. Better work on ints.

class Version implements Comparable<Version> {
    final int[] parts;
    Version(String vs) {
        parts = Stream.of(vs.split("\\.")).mapToInt(Integer::parseInt).toArray();
    }

    @Override
    public String toString() {
        return Arrays.stream(parts)
            .map(Integer::toString)
            .collect(Collectors.joining("."));
    }

    @Override
    public int compareTo(Version other) {
        return Arrays.compare(parts, other.parts);
    }
    ...
}

Version version1 = new Version("10.0.1");
Version version2 = new Version("1.2.1");
if (version1.compareTo(version2) <= 0) {
    System.out.printf("%s <= %s%n", version1, version2);
}

There is a coding principle on which this approach is based:

Do not use primitive types immediately for a specific quantity/entity. Wrap it in a value class.

CodePudding user response:

There is another way to convert each "." separated number to a fixed length string. For example, "1.2.3.4" becomes "0001000200030004" if the maximum number of digits for each number is 4. Use "****" if there are no numbers. ("****" is less than "0000") For example, "11.2" becomes "00110002********". You can compare strings thus converted with String.compare().

An example of sorting by converted numbers is shown below.

static final int NUMBER_SIZE = 4;
static final String UNDEF_NUMBER = "*".repeat(NUMBER_SIZE);
static final Pattern VERSION_PAT = Pattern.compile(
    "(\\d )\\.(\\d )(?:\\.(\\d )(?:\\.(\\d ))?)?");

static String fixed(String s) {
    return s == null ? UNDEF_NUMBER : "0".repeat(NUMBER_SIZE - s.length())   s;
}

public static String normalize(String version) {
    Matcher m = VERSION_PAT.matcher(version);
    if (!m.matches())
        throw new IllegalArgumentException("version");
    return fixed(m.group(1))   fixed(m.group(2))
           fixed(m.group(3))   fixed(m.group(4));
}

public static void main(String[] args) {
    String[] versions = {
        "10.1", "10.1.0", "10.2", "10.3", "10.1.0.0", "10.1.1.0",
        "10.2.1.0", "10.2.1.1", "10.2.0", "10.3.0", "11.1.1.0",
        "10.0", "9.1", "9.2", "9.1.1.0", "9.1.2.0"
    };
    record Pair(String version, String normalized) {}
    Arrays.stream(versions)
        .map(version -> new Pair(version, normalize(version)))
        .sorted(Comparator.comparing(Pair::normalized))
        .forEach(pair -> System.out.printf("s : %s%n", pair.version, pair.normalized));
}

output:

         9.1 : 00090001********
     9.1.1.0 : 0009000100010000
     9.1.2.0 : 0009000100020000
         9.2 : 00090002********
        10.0 : 00100000********
        10.1 : 00100001********
      10.1.0 : 001000010000****
    10.1.0.0 : 0010000100000000
    10.1.1.0 : 0010000100010000
        10.2 : 00100002********
      10.2.0 : 001000020000****
    10.2.1.0 : 0010000200010000
    10.2.1.1 : 0010000200010001
        10.3 : 00100003********
      10.3.0 : 001000030000****
    11.1.1.0 : 0011000100010000
  • Related