fnmatch()
La funzione fnmatch() in PHP confronta una stringa con un pattern wildcard della shell. Scopri sintassi, caratteri wildcard, flag e casi d'uso pratici.
Cos'è la Funzione fnmatch()?
La funzione fnmatch() verifica se una stringa corrisponde a un pattern wildcard della shell — lo stesso tipo di pattern che si digita in un terminale, come *.txt o image-?.png. Restituisce un boolean, quindi viene usata principalmente per filtrare nomi di file o altre stringhe senza scrivere un'espressione regolare completa.
Nonostante il nome, fnmatch() non accede mai al filesystem. Confronta soltanto il pattern con la stringa passata, quindi funziona su qualsiasi testo, non solo su file reali.
Questa pagina illustra la firma della funzione, i caratteri wildcard riconosciuti, i flag opzionali e i casi pratici in cui è preferibile sia a glob() che alle espressioni regolari.
Sintassi
fnmatch(string $pattern, string $filename, int $flags = 0): bool$pattern— il pattern wildcard della shell con cui confrontare.$filename— la stringa da verificare (non deve essere un file reale).$flags— flag bit opzionali che modificano il comportamento del confronto (vedi Flag).
La funzione restituisce true quando $filename corrisponde a $pattern, altrimenti false.
Esempio di Base
In questo caso myfile.txt corrisponde a *.txt, quindi viene eseguito il primo ramo e viene stampato The string matches the pattern!. Sostituendo la stringa con myfile.csv, il confronto fallisce.
Caratteri Wildcard
fnmatch() riconosce i wildcard standard della shell. Sapere esattamente cosa fa ognuno è fondamentale per usare la funzione correttamente:
| Wildcard | Significato | Pattern di esempio | Corrisponde a | Non corrisponde a |
|---|---|---|---|---|
* | Qualsiasi sequenza di caratteri (anche vuota) | *.log | error.log, .log | error.txt |
? | Esattamente un carattere | file?.txt | file1.txt | file12.txt |
[...] | Un carattere dell'insieme | image.[jp]ng | image.jng, image.png | image.gng |
[!...] | Un carattere non nell'insieme | [!0-9]* | abc | 1abc |
L'esempio seguente mostra ogni wildcard affiancato agli altri:
<?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 digitFlag
Il terzo argomento accetta una o più delle seguenti costanti, combinate con l'operatore OR bit a bit (|):
| Flag | Effetto |
|---|---|
FNM_NOESCAPE | Tratta il backslash (\) come carattere letterale invece di carattere di escape. |
FNM_PATHNAME | Uno slash (/) nella stringa deve essere abbinato a un / letterale — * e ? non lo abbineranno. |
FNM_PERIOD | Un punto iniziale nella stringa deve essere abbinato esplicitamente; * e ? non lo abbineranno. |
FNM_CASEFOLD | Confronto senza distinzione tra maiuscole e minuscole. |
FNM_CASEFOLD è il flag più usato nella pratica:
<?php
var_dump(fnmatch("*.PNG", "photo.png")); // bool(false) — case differs
var_dump(fnmatch("*.PNG", "photo.png", FNM_CASEFOLD)); // bool(true) — case ignoredCon FNM_PATHNAME, il wildcard * si ferma ai separatori di directory, utile quando si confrontano percorsi completi:
<?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 "/"Un Caso Pratico: Filtrare un Elenco di File
Un'operazione comune è mantenere solo le voci che corrispondono a un pattern. Poiché fnmatch() opera su stringhe normali, si abbina naturalmente ad 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));Questo stampa:
Array
(
[0] => notes.txt
[1] => draft.txt
)fnmatch() vs. glob() vs. Espressioni Regolari
Questi tre strumenti si sovrappongono, quindi scegliere quello giusto è importante:
- Usa
glob()quando vuoi leggere file reali dal disco che corrispondono a un pattern. Accede al filesystem e restituisce i percorsi corrispondenti. - Usa
fnmatch()quando hai già delle stringhe (nomi di file, chiavi, etichette) in memoria e hai bisogno solo di un controllo vero/falso rispetto a un pattern wildcard. - Usa
preg_match()quando hai bisogno della piena potenza delle espressioni regolari — gruppi di cattura, alternanza, quantificatori — che i semplici wildcard non possono esprimere.
Attenzioni
- Non è il filesystem.
fnmatch()non verifica che un file esista; confronta solo stringhe. Per l'accesso al disco usaglob(). - Disponibilità. Nelle versioni di Windows precedenti a PHP 7.2,
fnmatch()potrebbe non essere disponibile. Racchiudi le chiamate infunction_exists('fnmatch')se devi supportare quegli ambienti. - I pattern non sono regex.
*significa "qualsiasi carattere", non "zero o più occorrenze del token precedente". Se scrivia+aspettandoti un quantificatore regex, viene trattato come i due caratteri letteraliae+. - File nascosti. Per impostazione predefinita
*abbina un punto iniziale, quindi*corrisponde a.gitignore. AggiungiFNM_PERIODse vuoi ignorare i dotfile come fa la shell.
Conclusione
fnmatch() è il modo più semplice per verificare se una stringa corrisponde a un pattern wildcard in stile shell in PHP. Usala quando hai bisogno di un filtraggio rapido e leggibile dei nomi di file senza l'overhead di un'espressione regolare — e ricorda i suoi compagni glob() per leggere file dal disco e preg_match() per tutto ciò che è più complesso dei wildcard.