【问题标题】:Make PHP glob search order insensitive使 PHP glob 搜索顺序不敏感
【发布时间】:2018-05-12 18:44:05
【问题描述】:

我正在自学 php,所以如果这是一个愚蠢的问题,我很抱歉。我有一个包含许多文件夹的文件夹,所有文件夹都包含 JPG 文件。我正在使用下面的代码来搜索名称(和/或文件夹名称)包含用户发送的所有关键字的文件(在示例中限制为 4 个关键字)。如果关键字以与它们在文件夹/文件字符串中出现的顺序相同的顺序发送但不返回具有不同顺序的相同单词的字符串,则此方法可以正常工作。我怎样才能做到这一点?非常感谢!

<?php

$keywords = $_REQUEST['keywords'];

$exploded_keywords = explode(" ", $keywords );

if (isset($exploded_keywords[4])) { $inclusion = '*'.$exploded_keywords[0].'*'.$exploded_keywords[1].'*'.$exploded_keywords[2].'*'.$exploded_keywords[3].'*'.$exploded_keywords[4].'*'; } else { 

if (isset($exploded_keywords[3])) { $inclusion = '*'.$exploded_keywords[0].'*'.$exploded_keywords[1].'*'.$exploded_keywords[2].'*'.$exploded_keywords[3].'*'; } else { 

if (isset($exploded_keywords[2])) { $inclusion = '*'.$exploded_keywords[0].'*'.$exploded_keywords[1].'*'.$exploded_keywords[2].'*'; } else { 

if (isset($exploded_keywords[1])) { $inclusion = '*'.$exploded_keywords[0].'*'.$exploded_keywords[1].'*'; } else { 

if (isset($exploded_keywords[0])) { $inclusion = '*'.$exploded_keywords[0].'*'; }}}}}

$files = glob("$inclusion/*.[jJ][pP][gG]", GLOB_BRACE);

$num = $files[0];

for ($i=0; $i<count($files); $i++) { 
   $num = $files[$i]; 
   $err = 0;
   foreach($exclude as $term) {
      if (stristr($num,$term)) { 
         $err++; }}
   if( !$err > 0 ) { // display thumbnails... }} ?>

【问题讨论】:

  • 这样的? regex101.com/r/Y9qC25/2 请注意,我添加了 mg 标志以匹配多行。
  • 如果找到任何关键字,第一个返回匹配项。只有在找到所有关键字时才会匹配:regex101.com/r/DjzIyf/1
  • (与您的问题无关) 整套if (isset($exploded_keywords... 语句可以替换为$inclusion = '*'.str_replace(' ', '*', $keywords).'*';(即您甚至不需要explode($keywords)) .如果您需要将关键字的数量限制为 5 个,则可以使用 $exploded_keywords = explode(" ", $keywords); $inclusion = '*'.implode('*', array_slice($exploded_keywords, 0, 5)).'*';
  • @axiac 关键字的顺序他不会还有同样的问题吗?
  • @Lou 他当然会。我建议简化现有代码(鉴于 OP 正在学习 PHP)。我没有回答这个问题。

标签: php glob


【解决方案1】:

我会使用正则表达式来实现这一点。请参阅最后一段代码,了解不那么自我解释但直接的版本。

<?php
//Its bad practice to use $_REQUEST, you should use $_GET or $_POST if you can..
$keywords = $_REQUEST['keywords'];

//Let's prepare our regex to match our keywords.   
$exploded_keywords = explode(" ", $keywords );
$regex = "/";

//Loop trough your keywords and add them to the regex.
// ?= is a lookahead, if you want to know what it does. http://www.rexegg.com/regex-lookarounds.html
//preg_quote() will escape your keywords so they don't break your regex. Caracters such as ( ) . ? * etc.
foreach($exploded_keywords as $keyword){
    $regex .= "(?=.*".preg_quote($keyword, '/').")";
}

/* 
 * The following block of code has been added just in case it's useful to someone.
 * This will return a match if ANY one keyword is found within the file name. (Case insensitive)
 *
 * $regex = "/.*(";
 * $tmp = '';
 * foreach($exploded_keywords as $keyword) {
 *  $tmp = $tmp."|".preg_quote($keyword, '/');
 * }
 * $regex .= ltrim($tmp, '|') . ").*\.jpg/i";
 */
//match a jpg file. This version is case insensitive for the keywords and the extension.
$regex .=".*\.jpg/i";
//This would make it case sensitive but for the extension
//$regex .=".*\.[jJ][pP][gG]/";

//Now let's get the files
$files = glob("*.[jJ][pP][gG]", GLOB_BRACE);

//Let's get our matches
//preg_grep will look in your array values for matches and return the entries as a array. 
//array_values will reindex the keys of the returned array. Otherwise they keep their original keys. 
$matches = array_values(preg_grep($regex, $files));
//Verify your results
print_r($matches);

缩短版:

<?php
$keywords = preg_quote($_REQUEST['keywords']);
$regex = (!empty($keywords)) ? "/(?=.*". str_replace(' ', ')(?=.*', $keywords).")"  . ".*\.[jJ][pP][gG]/" : '/.*/';
$files = glob("*.[jJ][pP][gG]", GLOB_BRACE);
$matches = array_values(preg_grep($regex, $files));
print_r($matches);

编辑:在生成正则表达式时添加了 preg_quote(),因为关键字显然来自用户输入。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    • 2016-01-30
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多