2012-04-06 167 views
1

我需要搶出來的話這個字符串並將其替換AND LIKE/NOT在這樣一個SQL語句,但我拉我的頭髮試圖弄明白:-)PHP preg_match_all語法/正則表達式

$string = "hello -world !someword ! again |foo &foo AND foo ORfoo"; 
if (preg_match_all("/AND|OR|\||&|!|\-(\w+)/", "$string", $matches)) { 
     foreach ($matches as $match) { 
       foreach ($match as $m) { 
         // 1. figure out what the delimiter was (!, |, &, -, AND, OR 
         // 2. create a sql statement from it using the word following the delimiter 
         // Example: 
         if ($m = "!") { 
           $where .= " AND msg NOT like '%".$m."%'"; 
         } 
         if ($m = "AND") { 
           $where .= " AND msg like '%".$m."%'"; 
         } 
         if ($m = "OR") { 
           $where .= " OR msg like '%".$m."%'"; 
         } 
       } 
     } 
} 
echo $where; 

回答

2

使用下面的代碼來收集您的正則表達式匹配。請記住,preg_match_all是爲了收集給定模式的所有事件。注意我改用了preg_match。 「\ s *」允許您匹配空白(如果存在)。

$results = array(); 
$word_to_capture = '\s*(\w+)%'; 
$patterns[] = "%(AND)" . $word_to_capture; 
$patterns[] = "%(&)" . $word_to_capture; 
$patterns[] = "%(OR)" . $word_to_capture; 
$patterns[] = "%(\|)" . $word_to_capture; 
$patterns[] = "%(!)" . $word_to_capture; 
$patterns[] = "%(-)" . $word_to_capture; 

foreach($patterns as $p): 
    preg_match($p,$string,$matches); 
    $results[] = $matches; 
endforeach; 

然後,您可以遍歷$ results數組來創建MySQL查詢。結果數組看起來像這樣。

Array 
(
    [0] => Array 
     (
      [0] => AND foo 
      [1] => AND 
      [2] => foo 
     ) 

    [1] => Array 
     (
      [0] => &foo 
      [1] => & 
      [2] => foo 
     ) 

    [2] => Array 
     (
      [0] => ORfoo 
      [1] => OR 
      [2] => foo 
     ) 

    [3] => Array 
     (
      [0] => |foo 
      [1] => | 
      [2] => foo 
     ) 

    [4] => Array 
     (
      [0] => !someword 
      [1] => ! 
      [2] => someword 
     ) 

    [5] => Array 
     (
      [0] => -world 
      [1] => - 
      [2] => world 
     ) 

) 

我添加了一個額外的捕獲到正則表達式。你不同的模式將在元素1和單詞會在元素2.

您可以使用下面的代碼來創建查詢片段:

$query_fragment = ""; 
foreach($results as $r): 
    switch (trim($r[1])): 
     case "AND": 
      $query_fragment .= " AND msg LIKE '%" . $r[2] . "%'"; 
      break; 
     case "!": 
      $query_fragment .= " AND msg NOT LIKE '%" . $r[2] . "%'"; 
      break; 
     case "&": 
      $query_fragment .= " AND msg LIKE '%" . $r[2] . "%'"; 
      break; 
     case "OR": 
      $query_fragment .= " OR msg LIKE '%" . $r[2] . "%'"; 
      break; 
     case "|": 
      $query_fragment .= " OR msg LIKE '%" . $r[2] . "%'"; 
      break; 
    endswitch; 
endforeach; 
+0

這工作,謝謝! – 2012-04-06 23:45:43

+0

非常歡迎。我花了很長時間纔得到正則表達式。如果您願意將此答案標記爲正確答案,我將不勝感激。 – Odyssey 2012-04-07 00:31:58

1

您需要分別捕獲觸發器。那就是:

/(AND|OR|\|&|!-)(\w+)/ 

您的表達式當前只捕獲一個跟在短劃線之後的單詞。

循環也是不正確的。你想要的東西像

foreach ($matches[1] as $count => $match) { 
    if ($match == '!') { 
     $where . = " AND msg NOT LIKE '%" . $matches[2][$count] . "%'"; 
    } 
} 

SQL注入也可能是你的關注。