Java字符串匹配与通配符

3
我有一个带通配符X的模式字符串(例如:abc*)。
我还有一组字符串需要与给定的模式匹配。
例如:
abf - false abc_fgh - true abcgafa - true fgabcafa - false 我尝试使用正则表达式进行匹配,但它没有起作用。
这是我的代码:
String pattern = "abc*";
String str = "abcdef";

Pattern regex = Pattern.compile(pattern);

return regex.matcher(str).matches();

这会返回false

还有其他方法可以使它工作吗?

谢谢


你能展示一下你的代码吗?你想支持哪些通配符? - anubhava
为什么正则表达式没有起作用?你试了什么? - Ivar
这个应该很容易用正则表达式实现,只需将通配符替换为相应的表达式(例如,.*代替*.代替?),然后使用String#matches()函数即可。 - Thomas
@Thomas 那个方法不起作用,但他可以使用 String::startsWith 方法。但最好的方法是使用正则表达式。 - Sunflame
@Thomas 对不起,我误解了OP的问题,以为那是他的结果,而不是他想要的 - 在这种情况下使用 startsWith - Scary Wombat
显示剩余5条评论
5个回答

9

只需使用 Bash 风格的模式转换为 Java 风格的模式:

public static void main(String[] args) {
        String patternString = createRegexFromGlob("abc*");
        List<String> list = Arrays.asList("abf", "abc_fgh", "abcgafa", "fgabcafa");
        list.forEach(it -> System.out.println(it.matches(patternString)));
}

private static String createRegexFromGlob(String glob) {
    StringBuilder out = new StringBuilder("^");
    for(int i = 0; i < glob.length(); ++i) {
        final char c = glob.charAt(i);
        switch(c) {
            case '*': out.append(".*"); break;
            case '?': out.append('.'); break;
            case '.': out.append("\\."); break;
            case '\\': out.append("\\\\"); break;
            default: out.append(c);
        }
    }
    out.append('$');
    return out.toString();
}

是否有类似于java.util.regex的“glob”类型模式的等效物?
将通配符转换为正则表达式


请注意,String#matches()不需要将表达式包装在^...$中,因为这已经隐式完成了。 - Thomas
@Thomas - 已经注意到了。模式匹配也可以在没有^...$包装器的情况下工作。 - Sunil Kumar B M

2

you can use stringVariable.startsWith("abc")


无法运行...提供的输入模式是abc,基本上它可以是任何东西,例如.sh、abc*,我正在寻找Linux风格的模式匹配。 - Sunil Kumar B M

1

abc*是匹配ababcabccabccc等的正则表达式。
如果abc应该是匹配字符串的开头,并且后面可以有任何内容,则需要使用abc.*
否则,您可以在前面加上.*以匹配中间包含abc的字符串:.*abc.*

通常我建议使用this这样的网站来学习正则表达式。您正在寻找一个非常基本的模式,但很难说您确切需要什么。祝你好运!

编辑:
看起来您希望用户输入文件名的一部分(或类似内容),并且您想要提供类似搜索功能的东西(在我看来您应该在问题中明确说明)。在这种情况下,您可以从用户的输入中创建自己的正则表达式:

private Pattern getSearchRegEx(String userInput){
    return Pattern.compile(".*" + userInput + ".*");
}

当然,这只是一个非常简单的例子。您可以修改它,然后使用正则表达式来匹配文件名。

谢谢,但我真正想要的是类似于Linux风格的文件匹配,例如:ls .sh将给出所有以.sh结尾的文件,或者ls abc将给出以abc开头的文件...我无法控制模式或实际字符串... - Sunil Kumar B M
为什么您无法控制模式?用户输入模式吗? - bkis
是的,用户会提供模式输入,而字符串则是我必须匹配的文件名列表。 - Sunil Kumar B M

0

所以我想这里是你的答案: 您正在寻找的正则表达式是:[a][b][c].*

这是我的代码,它可以正常工作:

    String first = "abc"; // true
    String second = "abctest"; // true
    String third = "sthabcsth"; // false

    Pattern pattern = Pattern.compile("[a][b][c].*");

    System.out.println(first.matches(pattern.pattern())); // true
    System.out.println(second.matches(pattern.pattern())); // true
    System.out.println(third.matches(pattern.pattern())); // false

但是如果你只想检查字符串是否以某个字符开头或结尾,你可以使用 String 的方法:.startsWith().endsWith()


1
[a][b][c].* doesn't make sense. You are creating character classes with only one character in them. It's the same as abc.* - bkis
是的,你说得对。我正在使用IntelliJ内置的正则表达式检查,但不知道为什么它不能识别abc.*。 - Sunflame

0
  // The main function that checks if two given strings match. The pattern string  may contain
  // wildcard characters
  default boolean matchPattern(String pattern, String str) {

    // If we reach at the end of both strings, we are done
    if (pattern.length() == 0 && str.length() == 0) return true;

    // Make sure that the characters after '*' are present in str string. This function assumes that
    // the pattern string will not contain two consecutive '*'
    if (pattern.length() > 1 && pattern.charAt(0) == '*' && str.length() == 0) return false;

    // If the pattern string contains '?', or current characters of both strings match
    if ((pattern.length() > 1 && pattern.charAt(0) == '?')
        || (pattern.length() != 0 && str.length() != 0 && pattern.charAt(0) == str.charAt(0)))
      return matchPattern(pattern.substring(1), str.substring(1));

    // If there is *, then there are two possibilities
    // a: We consider current character of str string
    // b: We ignore current character of str string.
    if (pattern.length() > 0 && pattern.charAt(0) == '*')
      return matchPattern(pattern.substring(1), str) || matchPattern(pattern, str.substring(1));
    return false;
  }

  public static void main(String[] args) {
    test("w*ks", "weeks"); // Yes
    test("we?k*", "weekend"); // Yes
    test("g*k", "gee"); // No because 'k' is not in second
    test("*pqrs", "pqrst"); // No because 't' is not in first
    test("abc*bcd", "abcdhghgbcd"); // Yes
    test("abc*c?d", "abcd"); // No because second must have 2 instances of 'c'
    test("*c*d", "abcd"); // Yes
    test("*?c*d", "abcd"); // Yes
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接