【问题标题】:Regex - Match Pattern with list of values正则表达式 - 匹配模式与值列表
【发布时间】:2014-01-23 12:03:20
【问题描述】:

我有一个类似google.com 的输入和一个类似的值列表

 1. *.com
 2. *go*.com
 3. *abc.com
 4. *le.com
 5. *.*

我需要在 java 中编写一个模式,它应该返回除*abc.com 之外的所有匹配项。我尝试了一些,但没有按预期工作。请帮忙。提前致谢。

更新:

public static void main(String[] args) {
        List<String> values = new ArrayList<String>();
        values.add("*.com");
        values.add("*go*.com");
        values.add("*abc.com");
        values.add("*le.com");
        values.add("*.*");
        String stringToMatch = "google.com";
        for (String pattern : values) {
            String regex = Pattern.quote(pattern).replace("*", ".*");
            System.out.println(stringToMatch.matches(regex));
        }
    }

输出:

false
false
false
false
false

我试过了,但模式不匹配。

【问题讨论】:

  • 请发表您的尝试。
  • 我只能做反向匹配。即,输入 *.com 匹配 google.com

标签: java regex


【解决方案1】:

您可以将给定的模式转换为正则表达式,然后使用普通的正则表达式函数,如 String.matches():

for (String pattern : patterns) {
    final String regex = pattern.replaceAll("[\\.\\[\\](){}?+|\\\\]", "\\\\$0").replace("*", ".*");
    System.out.println(stringToMatch.matches(regex));
}

编辑:显然Pattern.quote() 只是在字符串周围添加\Q...\E。编辑为使用手动引用。

编辑2:另一种可能性是:

final String regex = Pattern.quote(pattern).replace("*", "\\E.*\\Q");

【讨论】:

  • \\E.*\\Q 是做什么的?该问题现已修复。
  • @RajaAsthana \Q 开始转义模式中的所有字符,\E 结束。因此\E.*\Q 将(未转义的)正则表达式.* 插入到转义序列中。
【解决方案2】:

基于previous answer of mine(阅读问题的cmets,很有启发性),这里有一个wildcardsToRegex方法:

public static String wildcardsToRegex(String wildcards) {

    String regex = wildcards;

    // .matches() auto-anchors, so add [*] (i.e. "containing")
    regex = "*" + regex + "*";
    // replace any pair of backslashes by [*]
    regex = regex.replaceAll("(?<!\\\\)(\\\\\\\\)+(?!\\\\)", "*");
    // minimize unescaped redundant wildcards
    regex = regex.replaceAll("(?<!\\\\)[?]*[*][*?]+", "*");
    // escape unescaped regexps special chars, but [\], [?] and [*]
    regex = regex.replaceAll("(?<!\\\\)([|\\[\\]{}(),.^$+-])", "\\\\$1");
    // replace unescaped [?] by [.]
    regex = regex.replaceAll("(?<!\\\\)[?]", ".");
    // replace unescaped [*] by [.*]
    regex = regex.replaceAll("(?<!\\\\)[*]", ".*");
    // return whether data matches regex or not

    return regex;

}

然后,在你的循环中,使用:

for (String pattern : values) {
    System.out.println(stringToMatch.matches(wildcardsToRegex(pattern)));
}

【讨论】:

  • 这与 Njol 的回答有何不同。你能解释一下吗?
  • @RajaAsthana 这个literally 将通配符字符串转换为正则表达式,而@Njol 的解决方案使用\Q...\E 转义序列(有关此语法的更多信息here,部分“特殊字符”,最后 §)。两者都有效。
【解决方案3】:

在您的代码中更改此行:

String regex = Pattern.quote(pattern).replace("*", ".*");

到这里:

String regex = pattern.replace(".", "\\.").replace("*", ".*");

【讨论】:

    【解决方案4】:

    你可以使用:

                List<String> values = new ArrayList<String>();
                values.add("*.com");
                values.add("*go*.com");
                values.add("*abc.com");
                values.add("*le.com");
                values.add("*.*");
                String stringToMatch = "google.com";
                for (String pattern : values) {
                    String regex = pattern.replaceAll("[.]", "\\.").replaceAll("[*]", "\\.\\*");
                    System.out.println(stringToMatch.matches(regex));
                }
    

    【讨论】:

      猜你喜欢
      • 2019-10-08
      • 1970-01-01
      • 2016-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多