Книга: Linux программирование в примерах
12.7.1. Простое сопоставление с шаблоном: fnmatch()
12.7.1. Простое сопоставление с шаблоном: fnmatch()
Мы начинаем с функции fnmatch()
(«filename match» — сопоставление имени файла»).
#include <fnmatch.h> /* POSIX */
int fnmatch(const char *pattern, const char *string, int flags);
Эта функция сопоставляет string
с pattern
, который является обычным шаблоном групповых символов оболочки. Значение флагов (которое вскоре будет описано) изменяет поведение функции. Возвращаемое значение равно 0, если string
соответствует pattern
, FNM_NOMATCH
, если не соответствует, и ненулевое значение, если возникла ошибка. К сожалению, POSIX не определяет каких-либо специфических ошибок; соответственно, вы можете лишь сказать, что что-то пошло не так, но не можете сказать, что.
Переменная flags
является побитовым ИЛИ одного или более флагов, перечисленных в табл. 12.1.
Таблица 12.1. Значения флагов для fnmatch()
Флаг | Только GLIBC | Значение |
---|---|---|
FNM_CASEFOLD |
? | Сопоставление с учетом регистра |
FNM_FILE_NAME |
? | Синоним GNU для FNM_PATHNAME |
FNM_LEADING_DIR |
? | Флаг для внутреннего использования GLIBC; не используйте его в своих программах. Подробности см. в fnmatch(3) |
FNM_NOESCAPE |
Обратный слеш является обычным символом, а не знаком перехода | |
FNM_PATHNAME |
Слеш в string должен соответствовать слешу в pattern , он не может быть подставлен через * , ? или '[...] ' |
|
FNM_PERIOD |
Начальная точка в string подходит, лишь если в pattern также есть начальная точка. Точка должна быть первым символом в string . Однако, если также установлен FNM_PATHNAME , точка, которая идет за слешем, также рассматривается как начальная |
fnmatch()
работает со строками из любого источника; сопоставляемые строки не обязательно должны быть действительными именами файлов. Хотя на практике fnmatch()
используется в коде, читающем каталог с помощью readdir()
(см раздел 5.3.1 «Базовое чтение каталогов»):
struct dirent dp;
DIR *dir;
char pattern[100];
/* ...заполнить шаблон, открыть каталог, проверить ошибки... */
while ((dp = readdir(dir)) != NULL) {
if (fnmatch(pattern, dir->d_name, FNM_PERIOD) == 0)
/* имя файла соответствует шаблону */
else
continue; /* не соответствует */
}
GNU ls
использует fnmatch()
для реализации своей опции --ignore
. Вы можете предоставить несколько игнорируемых шаблонов (с помощью нескольких опций). ls
сопоставляет каждое имя файла со всеми шаблонами. Она делает это с помощью функции file_interesting()
в ls.с
:
2269 /* Возвращает не ноль, если файл в 'next' должен быть перечислен. */
2270
2271 static int
2272 file_interesting(const struct dirent *next)
2273 {
2274 register struct ignore_pattern* ignore;
2275
2276 for (ignore = ignore_patterns; ignore; ignore = ignore->next)
2277 if (fnmatch(ignore->pattern, next->d_name, FNM_PERIOD) == 0)
2278 return 0;
2279
2280 if (really_all_files
2281 || next->d_name[0] !=
2282 || (all_files
2283 && next->d_name[1] != ' '
2284 && (next->d_name[1] || next->d_name[2] != '')))
2285 return 1;
2286
2287 return 0;
2288 }
Цикл в строках 2276–2278 сопоставляет имя файла со списком шаблонов для игнорируемых файлов. Если один из шаблонов подходит, файл не интересен и file_interesting()
возвращает false (то есть 0).
Переменная all_files
соответствует опции -А
, которая показывает файлы, имена которых начинаются с точки, но не являются '.
' и '..
'. Переменная really_all_files
соответствует опции -а
, которая предполагает -А
, а также показывает '.
' и '..
'. При наличии таких сведений, условие в строках 228–2284 может быть представлено следующим псевдокодом:
if (/* показать все файлы независимо от их имени (-а) */
OR /* первый символ имени не точка */
OR (/* показать файлы с точкой (-А) */
AND /* в имени файла несколько символов */
AND (/* второй символ не точка */
OR /* третий символ не завершает имя */)))
return TRUE;
ЗАМЕЧАНИЕ. fnmatch()
может оказаться дорогостоящей функцией, если она используется в локали с многобайтным набором символов. Обсудим многобайтные наборы символов в разделе 13.4 «Можете произнести это для меня по буквам?»
- Простое присваивание
- 12.4.2. Простое оконное приложение
- 2.2. Сопоставление
- Простое выделение памяти
- 6.1.3.1. Простое форматирование времени: asctime() и ctime()
- ПРИЛОЖЕНИЕ Б Сопоставление функций Windows, UNIX и библиотеки С
- Сопоставление с UNIX и библиотекой С
- Пример: простое последовательное копирование файла
- Пример: простое управление задачами
- Пример 4-3. Присваивание значений переменным простое и замаскированное
- 3.14.5 Сопоставление с датой и временем
- Простое представление книги - класс BOOK