|
|
 |
fnmatch (PHP 4 >= 4.3.0, PHP 5) fnmatch -- Match filename against a pattern Descriptionbool fnmatch ( string pattern, string string [, int flags] )
fnmatch() checks if the passed string would
match the given shell wildcard pattern.
This is especially useful for filenames, but may also be used on regular strings.
The average user may be used to shell patterns or at least in their simplest form
to '?' and '*' wildcards so using
fnmatch() instead of ereg() or
preg_match() for frontend search expression input may be
way more convenient for non-programming users.
Example 1.
Checking a color name against a shell wildcard pattern.
|
<?php
if (fnmatch("*gr[ae]y", $color)) {
echo "some form of gray ...";
}
?>
|
|
| Warning |
For now this function is not available on Windows or other non-POSIX
compliant systems.
|
See also glob(),
ereg(),
preg_match()
and the Unix manpage on fnmatch(3) for flag names
(as long as they are not documented here ).
User Contributed Notes
fnmatch
jcannonb at gmail dot com
06-May-2005 02:50
I wrote a better SQL match. The other one had bugs in it:
function sql_match($pattern,$data)
{
$lpattern=strtolower($pattern);
$ldata=strtolower($data);
$lp=strlen($lpattern);
$ld=strlen($ldata);
$ip=0;
$id=0;
for ($ip=0; $ip<$lp; $ip++)
{
if ($lpattern[$ip]=='%')
{
$ip++;
if ($ip >= $lp)
{
return true;
}
for (;;)
{
if ($lpattern[$ip] == $ldata[$id])
{
break;
}
else
{
$id++;
if ($id > $ld)
{
return false;
}
}
}
}
if ($lpattern[$ip] <> $ldata[$id])
{
return false;
}
$id++;
}
if ($ld >= $lp)
{
if ($lpattern[$lp-1] != '%')
{
return false;
}
}
return true;
}
jcannonb at gmail dot com
27-Apr-2005 11:04
/******************************************************************\
* sql_match Written by Joshua C. Butcher *
* Works like the like() functionality in SQL *
* %zealbot% matches zealbot 1234zealbot and zealbodt1234 *
* zealbot% matches zealbot1234 *
* %zealbot matches 1234zealbot *
* zealbot matches only zealbot *
/******************************************************************/
function sql_match($pattern,$data)
{
$lp=strlen($pattern);
$ld=strlen($data);
$ip=0;
$id=0;
for ($ip=0; $ip<$lp; $ip++)
{
if ($pattern[$ip]=='%')
{
$ip++;
if ($ip >= $lp)
{
return true;
}
for (;;)
{
if ($pattern[$ip] == $data[$id])
{
break;
}
else
{
$id++;
if ($id > $ld)
{
return true;
}
}
}
}
if ($pattern[$ip] <> $data[$id])
{
return false;
}
$id++;
}
if ($ld <> $lp)
{
return false;
}
return true;
}
jcl [atNOSPAM] jcl [dot] name
22-Nov-2004 09:49
Oooops, sorry, I did a mistake... Here is the right version :
function my_fnmatch ($pattern, $file)
{
$lenpattern = strlen($pattern);
$lenfile = strlen($file);
for($i=0 ; $i<$lenpattern ; $i++)
{
if($pattern[$i] == "*")
{
for($c=$i ; $c<max($lenpattern, $lenfile) ; $c++)
{
if(my_fnmatch(substr($pattern, $i+1), substr($file, $c)))
return true;
}
return false;
}
if($pattern[$i] == "[")
{
$letter_set = array();
for($c=$i+1 ; $c<$lenpattern ; $c++)
{
if($pattern[$c] != "]")
array_push($letter_set, $pattern[$c]);
else
break;
}
foreach($letter_set as $letter)
{
if(my_fnmatch($letter.substr($pattern, $c+1), substr($file, $i)))
return true;
}
return false;
}
if($pattern[$i] == "?") continue;
if($pattern[$i] != $file[$i]) return false;
}
if(($lenpattern != $lenfile) && ($pattern[$i - 1] == "?")) return false;
return true;
}
Cheers
Jean-Charles Lefebvre
jcl [atNOSPAM] jcl [dot] name
22-Nov-2004 09:41
I've found a bug in the my_fnmatch() function of 'michael at zend dot com'.
If you call :
my_fnmatch('c:/tem?', 'c:/tempo');
It will match, this is an error since the '?' generic character is supposed to match only one character.
The bug was hard to find since this is really an exception...
Here is my corrected version, I think it's bug-free now :)
function my_fnmatch ($pattern, $file)
{
$lenpattern = strlen($pattern);
$lenfile = strlen($file);
for($i=0 ; $i<$lenpattern ; $i++)
{
if($pattern[$i] == "*")
{
for($c=$i ; $c<max($lenpattern, $lenfile) ; $c++)
{
if(my_fnmatch(substr($pattern, $i+1), substr($file, $c)))
return true;
}
return false;
}
if($pattern[$i] == "[")
{
$letter_set = array();
for($c=$i+1 ; $c<$lenpattern ; $c++)
{
if($pattern[$c] != "]")
array_push($letter_set, $pattern[$c]);
else
break;
}
foreach($letter_set as $letter)
{
if(my_fnmatch($letter.substr($pattern, $c+1), substr($file, $i)))
return true;
}
return false;
}
if($pattern[$i] == "?") continue;
if($pattern[$i] != $file[$i]) return false;
}
if($pattern[$i - 1] == "?") return false;
return true;
}
The bug correction is at the end of the function (the 'if' test).
Cheers,
Jean-Charles Lefebvre
phlipping at yahoo dot com
06-Aug-2003 05:59
you couls also try this function that I wrote before I found fnmatch:
function WildToReg($str)
{
$s = "";
for ($i = 0; $i < strlen($str); $i++)
{
$c = $str{$i};
if ($c =='?')
$s .= '.'; // any character
else if ($c == '*')
$s .= '.*'; // 0 or more any characters
else if ($c == '[' || $c == ']')
$s .= $c; // one of characters within []
else
$s .= '\\' . $c;
}
$s = '^' . $s . '$';
//trim redundant ^ or $
//eg ^.*\.txt$ matches exactly the same as \.txt$
if (substr($s,0,3) == "^.*")
$s = substr($s,3);
if (substr($s,-3,3) == ".*$")
$s = substr($s,0,-3);
return $s;
}
if (ereg(WildToReg("*.txt"), $fn))
print "$fn is a text file";
else
print "$fn is not a text file";
michael at zend dot com
18-Apr-2003 06:18
Try this one, supporting all filename matching facilities:
// MY_FNMATCH
function my_fnmatch($pattern, $file)
{
for($i=0; $i<strlen($pattern); $i++) {
if($pattern[$i] == "*") {
for($c=$i; $c<max(strlen($pattern), strlen($file)); $c++) {
if(my_fnmatch(substr($pattern, $i+1), substr($file, $c))) {
return true;
}
}
return false;
}
if($pattern[$i] == "[") {
$letter_set = array();
for($c=$i+1; $c<strlen($pattern); $c++) {
if($pattern[$c] != "]") {
array_push($letter_set, $pattern[$c]);
}
else break;
}
foreach ($letter_set as $letter) {
if(my_fnmatch($letter.substr($pattern, $c+1), substr($file, $i))) {
return true;
}
}
return false;
}
if($pattern[$i] == "?") {
continue;
}
if($pattern[$i] != $file[$i]) {
return false;
}
}
return true;
}
me at lejfdiecks dot de
15-Apr-2003 09:46
I had the same problem ("Call to undefined function: fnmatch()") using PHP 4.2.3 on a hosted webserver; so I wrote "my own" fnmatch(). Hope it helps someone:
function fnmatch($strPattern, $strString)
// My fnmatch()
// Supports '?' and '*' as wildcards
{
$intPos = 0;
do
{
$strPatternChar = substr($strPattern, $intPos, 1);
$strStringChar = substr($strString, $intPos, 1);
if ($strPatternChar == '*')
{
$bolMatch = TRUE;
break;
}
$bolMatch = ($strPatternChar == $strStringChar) || ($strPatternChar == '?' && $strStringChar != '');
$intPos++;
} while (($bolMatch == TRUE) && ($intPos < max(strlen($strPattern), strlen($strString))));
return($bolMatch);
}
// Main program - test fnmatch() function
if (fnmatch('te?t', 'test'))
echo "Pattern <b>matches</b> string.";
else
echo "Pattern <b>does not</b> match string.";
| |