1

I'm only able to match simple patterns like: "[0-9]" with fnmatch("[0-9]", tocheck, 0).

If I try something more complicated with ? or . or even a combination of these how do I use fnmatch? I saw there are some flags that can do the trick, but I don't know how to use because I'm fairly new to C.

EDIT: I saw the comment asking to give more details:

#include <stdio.h>
#include <fnmatch.h>

int main(int argc, char **argv) {
    const char *patternOne = "[0-9]";
    const char *patternTwo = ".?[a-z0-9]*?*[a-z0-9]";
    int res = fnmatch(patternTwo, "0", 0);
    printf("Result: %d\n",  res);
}

If I use patternOne the result is 0 and if I change the string to match, the result change correctly. However if I use patternTwo I never get the 0 result for whatever string I pass to fnmatch. I need to match something like this in my program. It is for an university exam, so the patterns are very intricate.

hippietrail
  • 15,848
  • 18
  • 99
  • 158
sanchu
  • 11
  • 1
  • 3
  • This is not a standard C function. RTFM for the library that contains fnmatch(). – Lee Daniel Crocker May 29 '18 at 19:52
  • 1
    What is `fnmatch`? – Weather Vane May 29 '18 at 19:52
  • 1
    Please give sample input, desired output and actual output for a few cases. – Yunnosch May 29 '18 at 19:52
  • For reference, this is the definition of fnmatch: http://pubs.opengroup.org/onlinepubs/9699919799/ – Thomas Jager May 29 '18 at 19:53
  • If `fnmatch` is supposed to match patterns in a string, should you be using `['0'-'9']` and not `[0-9]`? Is there a similarity with `scanf`'s `%[]`specifer? – Weather Vane May 29 '18 at 20:00
  • 2
    The POSIX function fnmatch matches wildcard patterns, not regular expressions. Wildcard patterns are described in glob(7): http://man7.org/linux/man-pages/man7/glob.7.html . – FBergo May 29 '18 at 20:03
  • 1
    Please provide the complete code that fails to do what you expect. A complete example of the pattern and filename you want to match against, and the flags you have passed. – jxh May 29 '18 at 20:29
  • You may interest yourself in [regex.h](http://pubs.opengroup.org/onlinepubs/7908799/xsh/regex.h.html). – KamilCuk May 29 '18 at 21:23
  • Updated the question, I hope it is clear what I want to do. – sanchu May 30 '18 at 08:03
  • A more direct link to the `fnmatch()` POSIX spec: http://pubs.opengroup.org/onlinepubs/9699919799/functions/fnmatch.html – Michael Burr May 30 '18 at 08:13
  • 3
    As mentioned in a couple comments here, `fnmatch()` doesn't match regular expressions. As a quick example, the fact that `patternTwo` starts with a `'.'` character means it won't match `"0"` since for `fnmatch()` a period matches a period (not any character like in a regex). For example, try `fnmatch(patternTwo, ".x0y1", 0)` will will show a match. – Michael Burr May 30 '18 at 08:19

2 Answers2

4

Treat the pattern as a shell glob pattern. Given:

const char* patternTwo = ".?[a-z0-9]*?*[a-z0-9]";

There is no way "0" will match that. An example of a string that will match it would be: ".XaX9"

. matches .
X matches ?
a matches [a-z0-9]
X matches *?*
9 matches [a-z0-9]

The reason fnmatch() is different from glob() is so that the pattern "*" (which as a normal glob would match any string) will fail to match a file named ".profile" because dot files are treated as hidden (it is function designed to perform a file name match).

jxh
  • 69,070
  • 8
  • 110
  • 193
0
#define _GNU_SOURCE
#include <stdio.h>
#include <fnmatch.h>

int main(int argc, char **argv) {
    const char *patternOne = "[0-9]";
    const char *patternTwo = ".?[a-z0-9]*?*[a-z0-9]";
    int res = fnmatch(patternTwo, "0", FNM_EXTMATCH);
    printf("Result: %d\n",  res);
}

Set FNM_EXTMATCH flag can use like .?[a-z0-9]*?*[a-z0-9] with pattern

FNM_EXTMATCH Besides the normal patterns, also recognize the extended patterns introduced in ksh. The patterns are written in the form explained in the following table where pattern-list is a | separated list of patterns.

?(pattern-list) The pattern matches if zero or one occurrences of any of the patterns in the pattern-list allow matching the input string.

(pattern-list) The pattern matches if zero or more occurrences of any of the patterns in the pattern-list allow matching the input string.

+(pattern-list) The pattern matches if one or more occurrences of any of the patterns in the pattern-list allow matching the input string.

@(pattern-list) The pattern matches if exactly one occurrence of any of the patterns in the pattern-list allows matching the input string.

!(pattern-list) The pattern matches if the input string cannot be matched with any of the patterns in the pattern-list.

Linus
  • 1
  • 1