2013-02-27 64 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