PHP全局风格匹配

Chr*_*ian 10 php glob path pattern-matching

为了简短起见,我写了一个访问控制系统.

该系统的要求之一是通过将其与模式匹配来检查是否可以访问规范/规范化路径.

首先想到的是PREG,问题是,模式是基于文件的,即类似于接受的模式glob().基本上,它只是包含?(匹配一个任意字符)或*(匹配任何字符)的模式.

所以简单来说,我需要glob()在PHP上重新创建匹配功能.

示例代码:

function path_matches($path, $pattern){
    // ... ?
}

path_matches('path/index.php', 'path/*');        // true
path_matches('path2/', 'path/*');                // false
path_matches('path2/test.php', 'path2/*.php');   // true
Run Code Online (Sandbox Code Playgroud)

一个可能的解决方案是转换$pattern为正则表达而不是使用preg_match(),有没有其他方法?

注意:我不能使用正则表达式的原因是模式将由非程序员编写.

Int*_*idd 14

使用fnmatch(),似乎可以解决问题.

  • 好吧,帮不了你,祝你好运! (2认同)

Dav*_*dom 5

转换为正则表达式似乎是我的最佳解决方案.您需要做的就是转换*.*,转换?.preg_quote.然而,它并不像看起来那么简单,因为就你做事的顺序而言,这是一个鸡与蛋的问题.

我不喜欢这个解决方案,但它是我能想到的最好的:使用正则表达式来生成正则表达式.

function path_matches($path, $pattern, $ignoreCase = FALSE) {

  $expr = preg_replace_callback('/[\\\\^$.[\\]|()?*+{}\\-\\/]/', function($matches) {
    switch ($matches[0]) {
      case '*':
        return '.*';
      case '?':
        return '.';
      default:
        return '\\'.$matches[0];
    }
  }, $pattern);

  $expr = '/'.$expr.'/';
  if ($ignoreCase) {
    $expr .= 'i';
  }

  return (bool) preg_match($expr, $path);

}
Run Code Online (Sandbox Code Playgroud)

编辑添加了区分大小写选项.

看它工作


小智 5

自PHP 4.3.0起,PHP中已经有了一个函数.

fnmatch() 检查传递的字符串是否与给定的shell通配符模式匹配.