Search code examples
regexstringjava-8semantic-versioning

Unclosed character class in Java semver regex


Java 8 here. I'm being passed a String and I need to tell if it matches our interval rendition of a semantically-versioned JAR file or not, which:

  • Starts with any alphanumeric string (hyphens also allowed here)
  • Followed by a hypen (-)
  • Followed by normal semver:
    • Major release number; then
    • Minor release number; then
    • Patch number
  • Ending with a suffix of .jar

Examples of valid file names:

  • some-lib-1.4.17.jar
  • someLib-1.4.17.jar
  • somelib-0.12.0.jar

My best attempt thus far:

public boolean isValidJarName(String jarName) {
    String fileRegex = "^([a-zA-Z\\-))((\\d+)\\.(\\d+)\\.(\\d+)).jar";
    Pattern filePattern = Pattern.compile(fileRegex);
    Matcher matcher = filePattern.matcher(jarName);

    return matcher.matches();
}

However this gives me a compiler error: Unclosed character class. So something is wrong with my regex syntactically, but then I'm not even sure if its set up correctly to give me what I'm looking for. Any ideas where I'm going awry?


Solution

  • Besides that unclosed character class, there seems some more issues in your current regex,

    ^([a-zA-Z\\-))((\\d+)\\.(\\d+)\\.(\\d+)).jar
    

    If your intent is to just match, you don't need to unnecessarily group the regex and amount of grouping is heavy. Also you don't need to escape - while it is inside character class and is present either at start or end of the character class. Since your string has someLib which is more than one character, hence you need to have quantifier with character class and you need to escape last dot just before jar otherwise it may match any character which may not be desirable. The correct regex you can use is following,

    ^[a-zA-Z-]+\\d+\\.\\d+\\.\\d+\\.jar
    

    Here is the Java code,

    String jarName = "someLib-1.2.3.jar";
    String fileRegex = "^[a-zA-Z-]+\\d+\\.\\d+\\.\\d+\\.jar";
    Pattern filePattern = Pattern.compile(fileRegex);
    Matcher matcher = filePattern.matcher(jarName);
    
    System.out.println(matcher.matches());
    

    This now prints,

    true
    

    Also, you can write your regex more compactly like this to match the given text,

    ^[a-zA-Z]+-(\\d+\\.)+jar
    

    Where [a-zA-Z]+ matches one or more alphabets, - matches a hyphen, (\\d+\\.)+ matches one or more digits followed by literal dot and whole of it one or more times, then finally jar matches literal jar