fnmatch

(PHP 4 >= 4.3.0, PHP 5)

fnmatch -- 用模式匹配文件名

说明

bool fnmatch ( string pattern, string string [, int flags] )

fnmatch() 检查传入的 string 是否匹配给出的 shell 统配符 pattern

此函数对于文件名尤其有用,但也可以用于普通的字符串。普通用户可能习惯于 shell 模式或者至少其中最简单的形式 '?''*' 通配符,因此使用 fnmatch() 来代替 ereg() 或者 preg_match() 来进行前端搜索表达式输入对于非程序员用户更加方便。

例子 1. 用 shell 中的通配符模式匹配来检查颜色

<?php
if (fnmatch("*gr[ae]y", $color)) {
  echo
"some form of gray ...";
}
?>

警告

目前该函数无法在 Windows 或其它非 POSIX 兼容的系统上使用

参见 glob()ereg()preg_match() 和 UNIX 中 fnmatch(3) 的手册中的标志名(只要本文档中还未包括它们)。


add a note add a note User Contributed Notes
soywiz at php dot net
18-Jul-2006 10:12
A better "fnmatch" alternative for windows that converts a fnmatch pattern into a preg one. It should work on PHP >= 4.0.0

<?php
  
if (!function_exists('fnmatch')) {
       function
fnmatch($pattern, $string) {
           return @
preg_match('/^' . strtr(addcslashes($pattern, '\\.+^$(){}=!<>|'), array('*' => '.*', '?' => '.?')) . '$/i', $string);
       }
   }
?>
jsnell at networkninja dot com
03-Mar-2006 11:12
The last line of soywiz at gmail dot com windows replacement should be changed to:

   return preg_match('/' . $npattern . '$/i', $string);

otherwise, a pattern for *.xml will match file.xml~ or any else anything with the text *.xml in it, regardless of position.
soywiz at gmail dot com
26-Jul-2005 07:07
A "fnmatch" alternative that converts the pattern, to a valid preg one and uses preg_match then. It will work on windows.

<?php
if (!function_exists('fnmatch')) {
function
fnmatch($pattern, $string) {
   for (
$op = 0, $npattern = '', $n = 0, $l = strlen($pattern); $n < $l; $n++) {
       switch (
$c = $pattern[$n]) {
           case
'\\':
              
$npattern .= '\\' . @$pattern[++$n];
           break;
           case
'.': case '+': case '^': case '$': case '(': case ')': case '{': case '}': case '=': case '!': case '<': case '>': case '|':
              
$npattern .= '\\' . $c;
           break;
           case
'?': case '*':
              
$npattern .= '.' . $c;
           break;
           case
'[': case ']': default:
              
$npattern .= $c;
               if (
$c == '[') {
                  
$op++;
               } else if (
$c == ']') {
                   if (
$op == 0) return false;
                  
$op--;
               }
           break;
       }
   }

   if (
$op != 0) return false;

   return
preg_match('/' . $npattern . '/i', $string);
}
}
?>
phlipping at yahoo dot com
06-Aug-2003 06: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";