【问题标题】:Unclosed character class in Java semver regexJava semver 正则表达式中的未封闭字符类
【发布时间】:2019-07-15 17:22:41
【问题描述】:

这里是 Java 8。我被传递了一个String,我需要判断它是否与我们对语义版本化 JAR 文件的间隔再现相匹配,其中:

  • 以任何字母数字字符串开头(此处也允许使用连字符)
  • 后跟一个连字符 (-)
  • 后跟正常 semver:
    • 主要版本号;那么
    • 次要版本号;那么
    • 补丁号
  • .jar 后缀结尾

有效文件名示例:

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

迄今为止我最好的尝试:

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

但是这给了我一个编译器错误:Unclosed character class。所以我的正则表达式在语法上有些问题,但我什至不确定它是否正确设置为我正在寻找的东西。有什么想法会出错吗?

【问题讨论】:

  • [ 缺少结尾 ]。所以我想它应该是` String fileRegex = "^([a-zA-Z\\-]))((\\d+)\\.(\\d+)\\.(\\d+)).jar ";`
  • 您在正则表达式中写了) 而不是] 似乎有一个错字,并且您的字符类未关闭。尝试使用这个^([a-zA-Z\\-])((\\d+)\\.(\\d+)\\.(\\d+)).jar
  • 感谢@PushpeshKumarRajwanshi (+1) 摆脱了编译器错误,但我的所有示例仍然无法匹配(例如,someLib-1.2.3.jarmatcher.matches("someLib-1.2.3.jar") 上解析为 false 等。
  • @hotmeatballsoup:您的正则表达式中还有一些问题。让我通过一个答案来澄清一下。
  • "([a-zA-Z\\-]+)-(\\d+\\.\\d+\\.\\d+).jar"

标签: regex string java-8 semantic-versioning


【解决方案1】:

除了未封闭的字符类之外,您当前的正则表达式中似乎还有一些问题,

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

如果您的意图只是匹配,则不需要对正则表达式进行不必要的分组,并且分组的数量很大。此外,当 - 在字符类内部并且出现在字符类的开头或结尾时,您也不需要转义它。由于您的字符串具有多个字符的someLib,因此您需要具有字符类的量词,并且您需要在jar 之前转义最后一个点,否则它可能匹配任何可能不需要的字符。您可以使用的正确正则表达式如下,

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

这是Java代码,

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());

现在打印出来了,

true

此外,您可以像这样更紧凑地编写正则表达式以匹配给定的文本,

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

[a-zA-Z]+ 匹配一个或多个字母,- 匹配一个连字符,(\\d+\\.)+ 匹配一个或多个数字后跟文字点和整个点一次或多次,最后jar 匹配文字@987654333 @

【讨论】:

  • 从描述中,我得出的结论是,基本名称和版本号之间的连字符应该是强制性的,所以在[a-zA-Z-]+ 之后应该有另一个-。没有它,它仍然匹配所有示例,但也匹配,例如"foo1.2.3.jar".
  • @Holger:我完全同意你的观点,这就是为什么我故意没有从第一个正则表达式解决方案中删除连字符。事实上,更好的正则表达式应该是^([a-zA-Z]+-)+(\\d+\\.)+jar,因此它可以很好地匹配someLib-version-1.2.3.jar 之类的文本,而不仅仅是匹配----1.2.3.jar 之类的内容当然,正则表达式可以进一步改进,基于更多有效/无效样本.
  • 那么,建议使用([a-zA-Z]++-)++,避免回溯。
  • @Holger:是的,再次同意你的观点,因为这会使正则表达式更快。感谢您的建议。
猜你喜欢
  • 2013-01-01
  • 2015-04-02
  • 1970-01-01
  • 2015-06-06
  • 2022-07-07
  • 2017-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多