【问题标题】:Optimize Java Regular expression优化Java正则表达式
【发布时间】:2014-05-22 13:11:44
【问题描述】:

我有一个包含大量 if 语句的文件,如下所示:

if ((Pattern.compile("string1|String2|String3").matcher(text_str).find()) 
    && (Pattern.compile("String4|String5").matcher(text_str).find())
    && (Pattern.compile("String6|String7|String8").matcher(text_str).find())
    && (Pattern.compile("String9|String10").matcher(text_str).find())
    && (Pattern.compile("String11|String12").matcher(text_str).find())
    && (Pattern.compile("String13|String14").matcher(text_str).find())
    && (Pattern.compile("String15|String16").matcher(text_str).find())
    && (Pattern.compile("String17|String18").matcher(text_str).find())
    && (Pattern.compile("String19|String19|String20").matcher(text_str).find())
    ) {
    return true;

}

我基本上需要检查一个字符串,比如(伪代码):

String contains? (I have a) AND (cat OR dog OR fish) AND (and it) AND (eats OR drinks OR smells) AND (funny OR a lot OR nothing)

我如何通过大量检查使其更易于维护和更高效?

【问题讨论】:

  • 如果您的代码有效,最好转到codereview.stackexchange.com
  • 是 string1, string2 ... 文字字符串吗?
  • 所以当你说“String1”、“String2”等时,这些只是真实字符串的占位符,对吧?实际的字符串只是普通的旧字符串还是包含任何真正的正则表达式(例如,\d 等)?
  • 你匹配,好的,但是你用这些匹配做什么?
  • String1 等只是简单的旧词。我想检查一个句子是否满足某些模式,例如伪代码中的示例。

标签: java regex performance maintainability


【解决方案1】:

您可以通过一个正则表达式使用一系列前瞻来做到这一点:

return text_str.matches("(?s)^(?=.*(string1|String2|String3))(?=.*(String4|String5))(?=.*(String6|String7|String8))(?=.*(String9|String10))(?=.*(String11|String12))(?=.*(String13|String14))(?=.*(String15|String16))(?=.*(String17|String18))(?=.*(String19|String19|String20))");

【讨论】:

  • +1 最简单的答案,也许最好在变量上定义单词以获得更好的可见性和可维护性。
  • 是的,我考虑过这个选项,但我发现它很难维护。我可能做的是编写一个函数,从一组单词中生成这个正则表达式。此表达式是否适用于其中包含多行的字符串,例如 html 页面?
  • @Aboca 你通过添加一个 ?在它之后,.*? 很懒惰。它尝试匹配最少的字符。
  • @FarhadAliNoo 这个正则表达式不可能发生灾难性的回溯。使量词不情愿(或您所说的“懒惰”)绝对没有区别(原因与回溯无关)
  • @FarhadAliNoo 这是一个前瞻性。它会在匹配后立即停止消耗输入,因此实际上它是不情愿的 - 它的行为就像在 .* 之后有一个 ? 反正
【解决方案2】:

你可以有一个List<List<String>>,你可以编译成List<Pattern>

for(List<String> terms : listOfTerms) {
    String pattern = StringUtils.join(terms, "|");
    patterns.add(Pattern.compile(pattern));
}

然后检查:

for(Pattern p : patterns)
    if(!p.matches(string))
        return false;

return true;

这应该使检查更容易。为了定义最初的术语列表,数组实际上可能会更好用吗?像这样的:

String[][] terms = {{"cat", "dog"}, {"a", "b"}...};

它可以被格式化为看起来不错并且可以包含 cmets 等...

【讨论】:

    猜你喜欢
    • 2012-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-09
    相关资源
    最近更新 更多