2013-02-27 66 views
4

不区分大小写精确短语如果我有一个字符串"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

是否必须同时匹配 “perfectMatches” *的,以*? – 2013-02-27 23:59:47

+1

对不起,但我不明白这个问题。你能提供例子吗? – berty 2013-02-27 23:59:55

+0

@ExplosionPills命令无关紧要 – 2013-02-28 00:15:05

回答

1

这听起来像你的问题的第1部分已经解决,所以这个答案只关注第2部分。据我所知,你试图确定给定的输入消息是否包含任何顺序的所有单词列表。

对于每条消息,这可以通过正则表达式和单个preg_match来完成,但如果您有大量单词列表,则效率非常低。如果N是您搜索的词的数量,M是消息的长度,那么算法应该是O(N * M)。如果您发现,有在正则表达式每个关键字设置两个.*条款。使用lookahead断言,正则表达式引擎必须为每个关键字遍历一次。下面是示例代码:

<?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 
+1

感谢您的详细回复!我不是很清楚这个问题,所以这是我的错,但如果它是'$ keywords = array(array(“lose”,“weight”,“fast”),array(“call”,“now”, “free”));'并且我可以执行1个reg_ex并检查$ msg1以查看它是否匹配?所以使用这个关键字数组,你会在你的例子中得到相同的输出,但它也可以捕获$ msg4 =“想要免费的iPhone?现在调用”;。如果这是不可能的,那么我将不得不采取把它放在一个循环中,但我想避免这种情况。再次感谢! – 2013-03-02 19:58:34

+1

当然,这可以用1个正则表达式来完成,但为什么?你说你想避免一个循环,但从性能的角度来看它是没有意义的,因为循环**在正则表达式中出现。仅仅因为你不输入'for'并不意味着处理器不会迭代。做到这一点的最好方法是使用上面的索引方法。这样,每个消息只被搜索一次。对于多组关键字,您将不得不比较索引,而不是仅使用'min'函数,但它是相同的概念。 – 2013-03-03 00:02:47

+1

一个例子是:'$ patt ='/('; foreach($关键字为$ group){$ patt = $ patt。'(?=。* \ b'。implode($ group,'\ b。*) (?=。* \ b')。'\ b。*)|';} echo $ patt = substr($ patt,0,-1)。')/ i';'例如, /((?=.*\blose\b.*)(?=.*\bweight\b.*)(?=.*\bfast\b.*)|(?=.*\bcall\b.* )(?=。* \ bnow \ b。*)(?=。* \ bfree \ b。*))/ i'我绝对不建议您使用此正则表达式,但只是说这是可能的。正则表达式中的任何东西都是可能的。您可以将整个程序编写为1个正则表达式,但这并不意味着从性能或可读性的角度来看这是个好主意。 – 2013-03-03 00:03:30