W3docs

fnmatch()

Функция fnmatch() в PHP проверяет совпадение строки с шаблоном подстановки оболочки. Узнайте синтаксис, символы подстановки и флаги.

Что такое функция fnmatch()?

Функция fnmatch() проверяет, соответствует ли строка шаблону подстановки оболочки — такому же, какой вы вводите в терминале, например *.txt или image-?.png. Она возвращает boolean, поэтому чаще всего используется для фильтрации имён файлов или других строк без написания полного регулярного выражения.

Несмотря на название, fnmatch() никогда не обращается к файловой системе. Она только сравнивает шаблон со строкой, которую вы передаёте, поэтому работает с любым текстом, а не только с реальными файлами.

На этой странице рассматриваются сигнатура функции, символы подстановки, которые она понимает, необязательные флаги и практические случаи, когда она превосходит как glob(), так и регулярные выражения.

Синтаксис

fnmatch(string $pattern, string $filename, int $flags = 0): bool
  • $pattern — шаблон подстановки оболочки для сопоставления.
  • $filename — проверяемая строка (необязательно должна быть реальным файлом).
  • $flags — необязательные битовые флаги, изменяющие поведение сопоставления (см. Флаги).

Функция возвращает true, если $filename соответствует $pattern, и false в противном случае.

Базовый пример

php— editable, runs on the server

Здесь myfile.txt соответствует *.txt, поэтому выполняется первая ветка и выводится The string matches the pattern!. Замените строку на myfile.csv — и сопоставление завершится неудачей.

Символы подстановки

fnmatch() понимает стандартные символы подстановки оболочки. Точное знание того, что делает каждый из них, является ключом к правильному использованию функции:

Символ подстановкиЗначениеПример шаблонаСоответствуетНе соответствует
*Любая последовательность символов (включая пустую)*.logerror.log, .logerror.txt
?Ровно один символfile?.txtfile1.txtfile12.txt
[...]Один символ из набораimage.[jp]ngimage.jng, image.pngimage.gng
[!...]Один символ, не входящий в набор[!0-9]*abc1abc

Следующий пример демонстрирует каждый символ подстановки, чтобы вы могли увидеть их рядом:

<?php

var_dump(fnmatch("*.log", "error.log"));     // bool(true)  — * matches "error"
var_dump(fnmatch("file?.txt", "file1.txt")); // bool(true)  — ? matches one char
var_dump(fnmatch("file?.txt", "file12.txt"));// bool(false) — ? matches only ONE char
var_dump(fnmatch("img.[jp]ng", "img.png"));  // bool(true)  — p is in [jp]
var_dump(fnmatch("[!0-9]*", "abc"));          // bool(true)  — first char is not a digit
var_dump(fnmatch("[!0-9]*", "1abc"));         // bool(false) — first char IS a digit

Флаги

Третий аргумент принимает одну или несколько следующих констант, объединённых оператором побитового ИЛИ (|):

ФлагЭффект
FNM_NOESCAPEОбрабатывать обратную косую черту (\) буквально, а не как управляющий символ.
FNM_PATHNAMEКосая черта (/) в строке должна совпадать с буквальным /* и ? не будут её сопоставлять.
FNM_PERIODНачальная точка в строке должна совпадать явно; * и ? не будут её сопоставлять.
FNM_CASEFOLDСопоставление без учёта регистра.

FNM_CASEFOLD — это флаг, к которому вы будете обращаться чаще всего:

<?php

var_dump(fnmatch("*.PNG", "photo.png"));               // bool(false) — case differs
var_dump(fnmatch("*.PNG", "photo.png", FNM_CASEFOLD)); // bool(true)  — case ignored

С FNM_PATHNAME символ подстановки * останавливается на разделителях каталогов, что удобно при сопоставлении целых путей:

<?php

var_dump(fnmatch("src/*.php", "src/index.php"));               // bool(true)
var_dump(fnmatch("src/*.php", "src/lib/db.php"));              // bool(true)  — * crosses the slash
var_dump(fnmatch("src/*.php", "src/lib/db.php", FNM_PATHNAME));// bool(false) — * cannot cross "/"

Практический пример использования: фильтрация списка файлов

Распространённая задача — оставить только те элементы, которые соответствуют шаблону. Поскольку fnmatch() работает с обычными строками, она хорошо сочетается с array_filter():

<?php

$files = ["report.pdf", "notes.txt", "draft.txt", "image.png"];

$textFiles = array_filter($files, fn($file) => fnmatch("*.txt", $file));

print_r(array_values($textFiles));

Это выводит:

Array
(
    [0] => notes.txt
    [1] => draft.txt
)

fnmatch() vs. glob() vs. регулярные выражения

Эти три инструмента частично перекрываются, поэтому важно выбрать правильный:

  • Используйте glob(), когда хотите прочитать реальные файлы с диска, соответствующие шаблону. Она обращается к файловой системе и возвращает найденные пути.
  • Используйте fnmatch(), когда у вас уже есть строки (имена файлов, ключи, метки) в памяти и нужна только проверка true/false по шаблону подстановки.
  • Используйте preg_match(), когда нужна вся мощь регулярных выражений — группы захвата, чередование, кванторы — которые простые символы подстановки не могут выразить.

Подводные камни

  • Это не файловая система. fnmatch() не проверяет существование файла; она только сравнивает строки. Для доступа к диску используйте glob().
  • Доступность. В сборках Windows до PHP 7.2 функция fnmatch() может быть недоступна. Оберните вызовы в function_exists('fnmatch'), если необходима поддержка таких сред.
  • Шаблоны — это не регулярные выражения. * означает «любые символы», а не «ноль или более повторений предыдущего токена». Если вы напишете a+, ожидая квантор регулярного выражения, он будет трактоваться как два буквальных символа a и +.
  • Скрытые файлы. По умолчанию * соответствует начальной точке, поэтому * соответствует .gitignore. Добавьте FNM_PERIOD, если хотите пропускать файлы с точкой, как это делает оболочка.

Заключение

fnmatch() — самый простой способ проверить строку на соответствие шаблону подстановки в стиле оболочки в PHP. Используйте её, когда нужна быстрая, читаемая фильтрация имён файлов без накладных расходов регулярного выражения — и помните о её дополнениях: glob() для чтения файлов с диска и preg_match() для всего более сложного, чем символы подстановки.

Практика

Практика
Какие аргументы принимает функция fnmatch() в PHP?
Какие аргументы принимает функция fnmatch() в PHP?
Was this page helpful?