3

I have a pattern string with a wild card say X (E.g.: abc*).

Also I have a set of strings which I have to match against the given pattern.

E.g.:

abf - false

abc_fgh - true

abcgafa - true

fgabcafa - false

I tried using regex for the same, it didn't work.

Here is my code

String pattern = "abc*";
String str = "abcdef";

Pattern regex = Pattern.compile(pattern);

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

This returns false

Is there any other way to make this work?

Thanks

Sunil Kumar B M
  • 2,735
  • 1
  • 24
  • 31

5 Answers5

9

Just use bash style pattern to Java style pattern converter:

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

Is there an equivalent of java.util.regex for “glob” type patterns?
Convert wildcard to a regex expression

Dmitrii
  • 340
  • 2
  • 6
2

you can use stringVariable.startsWith("abc")

virus
  • 51
  • 4
  • that won't work... the input pattern provided is abc*, and basically, it could be anything like *.sh, abc*, I'm looking for linux style pattern matching – Sunil Kumar B M Jul 26 '17 at 08:55
1

abc* would be the RegEx that matches ab, abc, abcc, abccc and so on.
What you want is abc.* - if abc is supposed to be the beginning of the matched string and it's optional if anything follows it.
Otherwise you could prepend .* to also match strings with abc in the middle: .*abc.*

Generally i recommend playing around with a site like this to learn RegEx. You are asking for a pretty basic pattern but it's hard to say what you need exactly. Good Luck!

EDIT:
It seems like you want the user to type a part of a file name (or so) and you want to offer something like a search functionality (you could have made that clear in your question IMO). In this case you could bake your own RegEx from the users' input:

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

Of course that's just a very simple example. You could modify this and then use the RegEx to match file names.

bkis
  • 2,530
  • 1
  • 17
  • 31
  • Thanks.. but what I really want is linux style file matching like E.g: ls *.sh will give all files ending with .sh or ls abc* will give files starting with abc... I don't have control over the pattern or the actual strings... – Sunil Kumar B M Jul 26 '17 at 08:22
  • Why don't you have control over the pattern? Does a user input the pattern? – bkis Jul 26 '17 at 08:24
  • yes.. user give the pattern input.. and strings are a list of file names which I have to match – Sunil Kumar B M Jul 26 '17 at 08:25
0

So I thin here is your answer: The regexp that you are looking for is this : [a][b][c].*

Here is my code that works:

    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

But if you want to check only if starts with or ends with you can use the methods of String: .startsWith() and endsWith()

Sunflame
  • 2,993
  • 4
  • 24
  • 48
  • 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 Jul 26 '17 at 08:32
  • Yes you are right, I was checking with the IntelliJ built in Regexp check, and Idk why it didn't work with abc.*. – Sunflame Jul 26 '17 at 08:34
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
  }
Keshavram Kuduwa
  • 942
  • 10
  • 40