使 PHP glob 搜索顺序不敏感
Make PHP glob search order insensitive
我正在自学 php 如果这是一个愚蠢的问题,我很抱歉。我有一个包含许多文件夹的文件夹,所有文件夹都包含 JPG 文件。我正在使用下面的代码搜索名称(and/or 文件夹名称)包含用户发送的所有关键字的文件(示例中限制为 4 个关键字)。如果关键字的发送顺序与它们在 folder/file 字符串中出现的顺序相同,但不会返回具有不同顺序的相同单词的字符串,则此方法可以正常工作。我怎样才能做到这一点?非常感谢!
<?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... }} ?>
我会使用正则表达式来实现这一点。请参阅最后一段代码,了解更少的自我解释但直接的版本。
<?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(),因为关键字显然来自用户输入。
我正在自学 php 如果这是一个愚蠢的问题,我很抱歉。我有一个包含许多文件夹的文件夹,所有文件夹都包含 JPG 文件。我正在使用下面的代码搜索名称(and/or 文件夹名称)包含用户发送的所有关键字的文件(示例中限制为 4 个关键字)。如果关键字的发送顺序与它们在 folder/file 字符串中出现的顺序相同,但不会返回具有不同顺序的相同单词的字符串,则此方法可以正常工作。我怎样才能做到这一点?非常感谢!
<?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... }} ?>
我会使用正则表达式来实现这一点。请参阅最后一段代码,了解更少的自我解释但直接的版本。
<?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(),因为关键字显然来自用户输入。