2012-04-06 171 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注入也可能是你的关注。