【问题标题】:php string matching with wildcard *?php 字符串匹配通配符 *?
【发布时间】:2011-09-04 00:26:28
【问题描述】:

我想提供用通配符*匹配字符串的可能性。

例子

$mystring = 'dir/folder1/file';
$pattern = 'dir/*/file';

stringMatchWithWildcard($mystring,$pattern);  //> Returns true

示例 2:

$mystring = 'string bl#abla;y';
$pattern = 'string*y'; 

stringMatchWithWildcard($mystring,$pattern);  //> Returns true

我的想法是这样的:

function stringMatch($source,$pattern) {
    $pattern = preg_quote($pattern,'/');        
    $pattern = str_replace( '\*' , '.*?', $pattern);   //> This is the important replace
    return (bool)preg_match( '/^' . $pattern . '$/i' , $source );
}

基本上将* 替换为.*?(考虑在*nix 环境中* 匹配empty 字符串)©vbence

有什么改进/建议吗?

// 添加 return (bool) 因为 preg_match 返回 int

【问题讨论】:

    标签: php regex string-matching


    【解决方案1】:

    这里不需要preg_match。 PHP有一个通配符比较功能,专门针对这种情况做的:

    fnmatch()

    fnmatch('dir/*/file', 'dir/folder1/file') 可能已经为您工作了。但请注意,* 通配符同样会添加更多斜杠,就像 preg_match 一样。

    【讨论】:

    • 嗨马里奥。 fnmatches 还有一些其他功能,例如[]。我只需要* 作为“特殊字符”
    • fnmatch 在非 POSIX 系统上不受支持。 (我看到php5.3+现在也支持windows了)。所以这并不总是最好的方法
    【解决方案2】:

    你应该改用.*

    $pattern = str_replace( '*' , '.*', $pattern);   //> This is the important replace
    

    编辑:您的^$ 的顺序也有误。

    <?php
    
    function stringMatchWithWildcard($source,$pattern) {
        $pattern = preg_quote($pattern,'/');        
        $pattern = str_replace( '\*' , '.*', $pattern);   
        return preg_match( '/^' . $pattern . '$/i' , $source );
    }
    
    $mystring = 'dir/folder1/file';
    $pattern = 'dir/*/file';
    
    echo stringMatchWithWildcard($mystring,$pattern); 
    
    
    
    $mystring = 'string bl#abla;y';
    $pattern = 'string*y'; 
    
    echo stringMatchWithWildcard($mystring,$pattern); 
    

    工作演示:http://www.ideone.com/mGqp2

    【讨论】:

    • 我不知道我是否想给这个'dir//file''dir/*/file'匹配的可能性
    • .* 是贪婪的,它会吃掉你所有的字符串,而不仅仅是继续模式的最少字符数。因此,如果您在.* 之后有任何内容,结果将始终为 false。
    • 从你的描述中我认为这正是你想要对 .+? 做的事情。
    • @vbence preg_match('/.*a/', 'aa') ?
    • 好吧,看来match 会给出相同的结果。
    【解决方案3】:
    .+?
    

    对所有字符进行非贪婪匹配。这不等于“*”,因为它不会匹配空字符串。

    以下模式也将匹配空字符串:

    .*?
    

    所以...

    stringMatchWithWildcard ("hello", "hel*lo"); // will give true
    

    【讨论】:

    • 你认为我应该允许空字符串吗?也考虑 dir:'dir//file' 匹配 'dir/*/file' ?
    • 如果您希望它的工作方式类似于 OS shell 的工作方式,那么您必须允许空字符串。只需在 Windows 中尝试 echo &gt; hello 后跟 dir hello* 或在 *nix 中尝试 ls hello*。在这种情况下 * 匹配空字符串。
    • 用你的 -1 发​​表评论会很有礼貌。
    • 好样的!感谢 *nix 的比较! (我也没有 -1 你的回答,我没有理由这样做)
    • @yes123 是的,我知道,不是指责。 :)
    【解决方案4】:

    您混淆了结尾 ($) 和开头 (^)。这个:

    preg_match( '/$' . $pattern . '^/i' , $source );
    

    应该是:

    preg_match( '/^' . $pattern . '$/i' , $source );
    

    【讨论】:

      【解决方案5】:

      您将遇到的一个问题是对preg_quote() 的调用将转义星号字符。鉴于此,您的 str_replace() 将替换 *,但不会替换它前面的转义字符。

      因此,您应该将str_replace('*' ..) 更改为str_replace('\*'..)

      【讨论】:

      • 我从文档中错过了我的错。固定
      【解决方案6】:
      $pattern = str_replace( '\*' , '.+?', $pattern);   // at least one character
      

      【讨论】:

      • 请为您的代码添加一些解释 - 查看此问题的其他答案以获得一些灵感
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-01
      • 1970-01-01
      相关资源
      最近更新 更多