Patterns
Pattern matching
- Task: from a number of strings, filter only those resembling a given example
- Example string — pattern — has some special characters, describing string structure
- matching is testing if the whole string can be described by pattern
- searching is finding a substring that matches pattern
Shell patterns
Patterns are used in Linux Shell to filter files by their names.
They are used for filename generation before executing a Shell command.
Performed by Shell, not by command being called (i.e. not by ls
in the example below).
Details on Shell patterns can be found in this and that documents.
This example demonstrates using Shell patters by the ls utility:
$ ls
a a0 aa aaa aaaa abab abba acb b b0 bb bbb cabba cba
$ ls a*
a a0 aa aaa aaaa abab abba acb
$ ls a?b
acb
$ ls c*a
cabba cba
$ ls [ab]*
a a0 aa aaa aaaa abab abba acb b b0 bb bbb
$ ls *[a-z]
a aa aaa aaaa abab abba acb b bb bbb cabba cba
$ ls *[^a-z]
a0 b0
The same can be done with other Linux utilities such as: cp, mv, rm, cat, etc. For these tools, Shell will provide file names in exactly the same way.
Patterns in Linux utilities
Pattern matching is also used in some Linux utilities. For example, the find utility uses pattern to search for files in a directory hierarchy.
For example, the command below searches for PDF-files with the OS_
prefix
in a directory tree:
$ find . -name "OS_*.pdf"
./part2os/01_OS_Architecture/OS_Lecture_01.pdf
./part2os/02_C/OS_Lecture_02.pdf
./part2os/03_SystemCalls/OS_Lecture_03.pdf
./part2os/04_Linking/OS_Lecture_04.pdf
./part2os/05_Strings/OS_Lecture_05.pdf
./part2os/06_Processes/OS_Lecture_06.pdf
Patterns in C
Program in C sometimes need to whether a file name or path matches a specific pattern.
This can be done using the fnmatch function.
The function returns zero if the name matches the specified pattern.
The patterns are the same patterns as in Shell. Please pay attention for the flags
argument
of the function.
The example below matches pattern in argv[1]
and name in argv[2]
:
Command:
tatarnikov@akos:~$ ./match "/h*/*ov" "/home/tatarnikov"
'/home/tatarnikov' matches '/h*/*ov'
Code:
#include <stdio.h>
#include <fnmatch.h>
int main(int argc, char *argv[]) {
const char* pattern = argv[1];
const char* name = argv[2];
if (fnmatch(pattern, name, FNM_PATHNAME) == 0) {
printf("'%s' matches '%s'\n", name, pattern);
} else {
printf("'%s' mismatches '%s'\n", name, pattern);
}
return 0;
}
Limitations of patterns
Patterns are good at filtering string that can be described by a simple template (e.g. file name). However, they are not suitable for more complex tasks. For such tasks, a more powerful tool required - regular expressions.