如果我有一个字符串"Hello I went to the store today"
并且我有一系列匹配
$perfectMatches = array("i went","store today");
它应该匹配这两者。 (数组可以变得非常大,所以我更喜欢在1 preg_match中进行)
编辑:让这个工作!谢谢!
preg_match_all("/\b(" . implode($perfectMatches,"|") . ")\b/i", $string, $match1)
我还需要一个单独的正则表达式,这很难解释。说我有一个数组
$array = array("birthday party","ice cream");//this can be very long
如果“生日”和“派对”以及字符串中的任何位置,是否可以获得与字符串匹配的正则表达式?
所以它应该匹配“嗨,这是我的生日,我要参加派对”?但是“冰淇淋”也在1 preg_match中?
由于
编辑:示例...
用户提交项目说明,我想检查垃圾邮件。我知道大多数垃圾邮件帖子都有“个人支票”或“特价”这样的短语,所以我想获得所有这些短语的列表并查看说明。如果说明中包含我的列表中的任何短语,则会将其标记为垃圾邮件。此场景适用于我想要的第一个正则表达式。
第二个正则表达式是,如果我知道某些垃圾邮件帖子在那里的某处有“丢失”,“重量”,“快”,则不必按任何顺序排列,但这3个单词在说明中。因此,如果我得到这些短语的列表“快速减肥”,“需要信用卡”并查看说明,我可以将其标记为垃圾邮件
答案 0 :(得分:1)
听起来问题的第1部分已经解决了,所以这个答案只关注第2部分。据我所知,你试图确定给定的输入消息是否包含任何顺序的所有单词列表。
对于每条消息,可以使用正则表达式和单个preg_match
来完成,但如果您有大量的单词列表,效率非常低。如果N是您要搜索的单词数,M是消息的长度,则算法应为O(N * M)。如果您注意到,每个关键字的正则表达式中有两个.*
个术语。使用前瞻断言,正则表达式引擎必须遍历每个关键字一次。以下是示例代码:
<?php
// sample messages
$msg1 = "Lose all the weight all the weight you want. It's fast and easy!";
$msg2 = 'Are you over weight? lose the pounds fast!';
$msg3 = 'Lose weight slowly by working really hard!';
// spam defining keywords (all required, but any order).
$keywords = array('lose', 'weight', 'fast');
//build the regex pattern using the array of keywords
$patt = '/(?=.*\b'. implode($keywords, '\b.*)(?=.*\b') . '\b.*)/is';
echo "The pattern is: '" .$patt. "'\n";
echo 'msg1 '. (preg_match($patt, $msg1) ? 'is' : 'is not') ." spam\n";
echo 'msg2 '. (preg_match($patt, $msg2) ? 'is' : 'is not') ." spam\n";
echo 'msg3 '. (preg_match($patt, $msg3) ? 'is' : 'is not') ." spam\n";
?>
输出结果为:
The pattern is: '/(?=.*\blose\b.*)(?=.*\bweight\b.*)(?=.*\bfast\b.*)/is'
msg1 is spam
msg2 is spam
msg3 is not spam
这第二个解决方案似乎更复杂,因为代码更多,但正则表达式更简单。它没有先行断言,也没有.*
个术语。 preg_match
函数在while
循环中调用,但这并不是什么大问题。每条消息只遍历一次,复杂度应为O(M)。这也可以使用单个preg_match_all
函数完成,但是您必须执行array_search
才能获得最终计数。
<?php
// sample messages
$msg1 = "Lose all the weight all the weight you want. It's fast and easy!";
$msg2 = 'Are you over weight? lose the pounds fast!';
$msg3 = 'Lose weight slowly by working really hard!';
// spam defining keywords (all required, but any order).
$keywords = array('lose', 'weight', 'fast');
//build the regex pattern using the array of keywords
$patt = '/(\b'. implode($keywords,'\b|\b') .'\b)/is';
echo "The pattern is: '" .$patt. "'\n";
echo 'msg1 '. (matchall($patt, $msg1, $keywords) ? 'is' : 'is not') ." spam\n";
echo 'msg2 '. (matchall($patt, $msg2, $keywords) ? 'is' : 'is not') ." spam\n";
echo 'msg3 '. (matchall($patt, $msg3, $keywords) ? 'is' : 'is not') ." spam\n";
function matchall($patt, $msg, $keywords)
{
$offset = 0;
$matches = array();
$index = array_fill_keys($keywords, 0);
while( preg_match($patt, $msg, &$matches, PREG_OFFSET_CAPTURE, $offset) ) {
$offset = $matches[1][1] + strlen($matches[1][0]);
$index[strtolower($matches[1][0])] += 1;
}
return min($index);
}
?>
输出结果为:
The pattern is: '/(\blose\b|\bweight\b|\bfast\b)/is'
msg1 is spam
msg2 is spam
msg3 is not spam