我为逻辑表达式创建了一个简单的语法,使用布尔运算符和字符串作为操作数,我计划将其作为URL查询字符串传递。我将根据$query
字符串中的操作数是否存在于另一个字符串$text
中来使用它来匹配字符串。
考虑以下示例(在PHP中):
function search($text, $query) // $text, $query are strings
{
// returns true if logical expression built from $query is true for $test string
// otherwise returns false. $query explained:
// (1) variables in $query are strings between brackets and operators
// (2) operators are: &=and, |=or, !=not
// (3) priority of logical operations is defined by brackets: ()
// (4) variable = true if substring exists in $text, false if not
}
// examples:
$text1 = 'str4 str3 blalbablastr2';
$text2 = 'str4whateverhere str3str5';
// str5 is present or str1 is present
$simpleQuery = 'str5|str1';
// (str1 or str2 present), (str3 present), and (str4 present or str5 not present)
$complexQuery = '(str1|str2)&str3&(str4|!str5)';
search($text1, $simpleQuery); // returns false as 'str5' OR 'str1' = false
search($text2, $simpleQuery); // returns true as 'str5' = true
search($text1, $complexQuery); // returns true as 'str2' AND 'str3' AND ('str4' AND NOT 'str5') = true
search($text2, $complexQuery); // returns false as 'str1' OR 'str2' = false
我可以使用“传统”方法编写搜索功能:
但是我相信有更短的&更快的方法使用正则表达式。如果你知道正则表达式足以提供实际帮助,请帮忙。谢谢!
答案 0 :(得分:0)
如果您只想匹配字符串,则可能不需要编写search
函数。 preg_match会执行示例中的搜索功能。
如果你不理解正则表达式在http://www.regular-expressions.info/的工作方式,你可以找到它们。
答案 1 :(得分:0)
你正在寻找绕过“传统”方法的方法,但即使采用正则表达式方法,你仍然需要完成你勾勒出的大部分步骤:
我认为如果你根本不使用你的语法,你只会从正则表达式方法中获得优势,并将你的过滤器存储为正则表达式。
以下是一些可以产生与过滤器相同结果的正则表达式的示例:
# simpleQuery
str5|str1
# complexQuery (with lookahead)
(?=.*(str1|str2))
(?=.*str3)
((?=.*str4)|(?!.*str5))
当您开始添加连词时(如complexQuery
中所述),您最终必须明确涵盖我使用lookaheads处理的搜索字词的不同顺序。
在简单的语言中,complexQuery
中的前瞻只是说明搜索字符串中存在一些位置:
如果没有前瞻,complexQuery
的前两行必须写成:
((str1|str2).*str3)|(str3.*(str1|str2))
当您添加更多连词时,第二种方法将变得非常笨拙。
正如你所看到的,正则表达式并不像你的语法那样漂亮,而且我认为你原来的方法可能是最好的。
答案 2 :(得分:0)
这就是我使用eval()解决自己问题的方法。 也许不是最好的解决方案(由于eval),但它确实有效。
注意:为了让生活更轻松,我将$ query中的子句与周围的引号区分开来。
class QueryText
{
/**
* Parses $query and performs search in $text
*
* @param string $query query string, PHP syntax, search strings should be in commas
* @param string $text content to searhc
* @param array $options
*
* @return mixed true on success,
* false on failure,
* null if parsing error
*
*/
public function search($query, $text, $options)
{
$defaultOptions =
[
'caseSensitive' => false
];
$options = array_merge($defaultOptions, $options);
$text = ($options['caseSensitive']) ? $text : mb_strtolower($text);
$query = ($options['caseSensitive']) ? $query : mb_strtolower($query);
if (!self::isValid($query, $text)) return null;
$evalStr = self::parse($query, $text);
// prepare for execution
$evalStr = 'return ((' . $evalStr . ') ? 1 : 0);';
$result = eval($evalStr);
return ($result===false) ? null : (($result===1) ? true : false);
}
private function isValid($query, $text)
{
// 1. check general syntax: should be any strings in quotes; left symbols should be &&, ||, (, ), !, spaces
$regex = '/("[^"\']+")|(\'[^\'"]+\')|(&&)|(\|\|)|([!()\s])/';
$str = preg_replace($regex, '', $query);
if ($str!=='') return false;
// 2. check brackets: should be even
$regex = '/([()])/';
$matches = [];
preg_match_all($regex, $query, $matches);
if (count($matches[0])%2 !== 0) return false;
// 3. check parsed expression
$regex = '/(\|&)|(&\|)|(&\))|(\(&)|(\(\|)|(\|\))|(&&&)|(\|\|\|)|(!\))|(^&)|(^\|)|(^\))|(&$)|(\|$)|(!$)|(\($)/';
$str = self::parse($query, $text);
$matches = [];
preg_match_all($regex, $str, $matches);
foreach($matches as $match)
if (count($match)!==0) return false;
return true;
}
private function parse($query, $text)
{
// inject true/false instead of strings
$regex = '/("[^"\']+")|(\'[^\'"]+\')/';
$evalStr = preg_replace_callback(
$regex,
function($matches) use($text)
{
if (trim($matches[0])=='') return '';
$str = $matches[0];
$str = trim($str); // remove spaces
$str = substr($str, 1); // remove left quote
$str = substr($str, 0, -1); // remove right quote
if (strpos(trim($text), $str) !== false) return 'true';
return 'false';
},
$query);
// remove spaces and return result
$regex = '/([\s]+)/';
return preg_replace($regex, '', $evalStr);
}
}
答案 3 :(得分:-2)
你可以看看这里 http://tr1.php.net/preg_match http://tr1.php.net/preg_match_all
if (preg_match("/php/i", "PHP is the web scripting language of choice.")) {
echo "A match was found.";
} else {
echo "A match was not found.";
}