使用REGEXP和IMPLODE时转义方括号

时间:2015-09-17 16:35:41

标签: php mysql regex

我有一个带有名字的数组和一个带有全名的mysql表上的列(名字在方括号中有几次)。正确的mysql语句如何比较数组的元素和列的元素,并且仅当第一个名称在数组中并且在方括号中时才返回全名?

   id      |      full_names

-----------------------------------
    1       |   [John] Mclay
    2       |   [John] Rossi
    3       |   Will John
    4       |   [Brian] Cosby
    5       |   Brian O'neal
$names_array=array("[John]" ,"[Brian]");

sql_query="SELECT full_names FROM myTable
              WHERE full_names REGEXP '^(".implode("|", $names_array).")[[:>:]]'"; 

结果我想只有第一个,第二个和第四个全名。 我的问题是因为方括号。数组中的每个名称都有2个方括号,对于每个名称,我必须使用\\两次才能转义特殊字符。但是我如何将其与implode结合使用呢?先感谢您!

2 个答案:

答案 0 :(得分:2)

  

但是如何将其与implode结合使用呢?

     
    

会给我一个像\[John\]\|\[Brian\]这样的字符串。但这不是我想要的。

  

这是预期的行为,因为“|”是一个正则表达式元字符。因此,请先逃避$names_array 第一次

中的正则表达式元字符
// Loop the array and escape each item with preg_quote
foreach($names_array as $index => $name) {
    $names_array[$index] = preg_quote($name);
}

但是,为了将其作为字符串传递给MySQL,您还需要转义反斜杠和单引号。我们可以在这里使用str_replace

// Escape backslashes and single quotes for SQL
$names_array = str_replace( array("\\","'"), array("\\\\","\\'"), $names_array);

注意:这应该通过 mysqli_real_escape_string来完成。 这仅适用于此问题的范围。

现在,我们可以最终添加管道进行更改。

你还有一件事要纠正。您使用的是POSIX word bounday [[:>:]],它位于前面有单词字符但后面没有单词字符的位置。但是,“]是一个单词字符。所以它与你的例子不符。

如果您想检查名称后面是否有“”空格,只需将其放入您的模式中:

$sql_query="SELECT full_names FROM myTable
              WHERE full_names REGEXP '^(".implode("|", $names_array).") '";
                                                                        ^
                                                                 (here) ^

代码:

$names_array = array("[John]" ,"[Brian]");

// Loop the array and escape each item with preg_quote
foreach($names_array as $index => $name) {
    $names_array[$index] = preg_quote($name);
}

// Escape backslashes and single quotes for SQL
$names_array = str_replace( array("\\","'"), array("\\\\","\\'"), $names_array);

// Now you can add "|"s that won't be escaped
$sql_query="SELECT full_names FROM myTable
              WHERE full_names REGEXP '^(".implode("|", $names_array).") '";

Run this code here

$ sql_query的值:

SELECT full_names FROM myTable
              WHERE full_names REGEXP '^(\\[John\\]|\\[Brian\\]) '

MySQL查询结果:

[John] Mclay
[John] Rossi
[Brian] Cosby

Test in SQL Fiddle

答案 1 :(得分:0)

在将names_array发送到内爆帮助之前,是否使用array_map修改了names_array?

未经测试的例子:

$names_for_regex = array_map(function($name){
     return preg_quote($name) ; // the next statement might be more suitable
     return '('.preg_quote($name).')' ;
}, $names);