Java中的通配符匹配

Joh*_*itb 10 java regex wildcard

我正在编写一个简单的调试程序,它将输入简单的字符串作为输入,可以包含星号以指示通配符匹配

*.wav  // matches <anything>.wav
(*, a) // matches (<anything>, a)
Run Code Online (Sandbox Code Playgroud)

我以为我会简单地采用该模式,在其中转义任何正则表达式特殊字符,然后将其替换\\*.*.然后使用正则表达式匹配器.

但我找不到任何Java函数来逃避正则表达式.我能找到的最佳匹配Pattern.quote,然而这正好将\Q\E在开始和字符串的结尾.

Java中是否有任何东西可以让您简单地进行通配符匹配而无需从头开始实现算法?

Boh*_*ian 15

逃避一切 - 不会有任何伤害.

    String input = "*.wav";
    String regex = ("\\Q" + input + "\\E").replace("*", "\\E.*\\Q");
    System.out.println(regex); // \Q\E.*\Q.wav\E
    System.out.println("abcd.wav".matches(regex)); // true
Run Code Online (Sandbox Code Playgroud)

或者您可以使用字符类:

    String input = "*.wav";
    String regex = input.replaceAll(".", "[$0]").replace("[*]", ".*");
    System.out.println(regex); // .*[.][w][a][v]
    System.out.println("abcd.wav".matches(regex)); // true
Run Code Online (Sandbox Code Playgroud)

通过将字符放入字符类来"转义"字符更容易,因为在字符类中几乎所有字符都会失去任何特殊含义.除非您期待奇怪的文件名,否则这将起作用.

  • 如果被搜索的文本包含"\ E",这不会中断吗?您可以使用Pattern.quote(String)来避免这种情况. (2认同)

zx8*_*x81 13

使用简单的正则表达式

这种方法的一个好处是我们可以轻松添加令牌*(请参阅底部添加令牌).

搜索: [^*]+|(\*)

  • |匹配的左侧是任何不是星星的字符
  • 右侧将所有星星捕获到第1组
  • 如果组1为空:替换为\Q+ Match +E
  • 如果设置了组1:替换为 .*

这是一些工作代码(参见在线演示的输出).

输入: audio*2012*.wav

输出: \Qaudio\E.*\Q2012\E.*\Q.wav\E

String subject = "audio*2012*.wav";
Pattern regex = Pattern.compile("[^*]+|(\\*)");
Matcher m = regex.matcher(subject);
StringBuffer b= new StringBuffer();
while (m.find()) {
    if(m.group(1) != null) m.appendReplacement(b, ".*");
    else m.appendReplacement(b, "\\\\Q" + m.group(0) + "\\\\E");
}
m.appendTail(b);
String replaced = b.toString();
System.out.println(replaced);
Run Code Online (Sandbox Code Playgroud)

添加令牌

假设我们还想?用一个点来转换代表单个字符的通配符.我们只是在正则表达式中添加一个捕获组,并将其从左侧的matchall中排除:

搜索: [^*?]+|(\*)|(\?)

在替换函数中我们添加如下内容:

else if(m.group(2) != null) m.appendReplacement(b, "."); 
Run Code Online (Sandbox Code Playgroud)


Mar*_*gor 8

Apache Commons-IO库中有一个小实用工具方法:org.apache.commons.io.FilenameUtils #wildcardMatch(),您可以使用它而不需要复杂的正则表达式.

API文档可以在以下网址找到:https://commons.apache.org/proper/commons-io/javadocs/api-2.5/org/apache/commons/io/FilenameUtils.html#wildcardMatch(java.lang.String,% 20java.lang.String)