preg_replace :在单引号转义表达式中捕获单引号

preg_replace : capturing single quote inside single quote escaped expression

在 wordpress 主题中,我使用 "posts_where" 过滤器将搜索添加到 "excerpt" 字段。它在搜索字符串中存在单引号时除外,导致 SQL 语法错误。

这似乎是 preg_replace 函数中 posts_where 过滤器的错误。

例如,对于字符串 "o'kine" ,在 posts_where 过滤器中接收到的 $where 字符串是:

"AND (((cn_posts.post_title LIKE '%o\'kine%') OR (cn_posts.post_content LIKE '%o\'kine%')))"

然后这是我 preg_replace 添加 post_excerpt 字段:

$where = preg_replace(
"/post_title\s+LIKE\s*(\'[^\']+\')/",
"post_title LIKE ) OR (post_excerpt LIKE ", $where );

以及 $where 之后的值:

"AND (((cn_posts.post_title LIKE '%o\') OR (post_excerpt LIKE '%o\'kine%') OR (cn_posts.post_content LIKE '%o\'kine%')))"

查看导致 SQL 语法错误的“%o\”部分。

预期结果为:

"AND (((cn_posts.post_title LIKE '%o\'kine%') OR (post_excerpt LIKE '%o\'kine%') OR (cn_posts.post_content LIKE '%o\'kine%')))"

错误显然在我的正则表达式中,更准确地说是在我的捕获括号中。我不知道如何处理我的搜索字符串中出现零个或多个单引号的可能性?

编辑:对于 Casimir et Hippolyte 的回答,这是在搜索字符串中使用单引号的有效过滤器:

function cn_search_where( $where ) {

    $where = preg_replace(
    "/post_title\s+LIKE\s*('[^'\\]*+(?s:\\.[^'\\]*)*+')/",
    "post_title LIKE ) OR (post_excerpt LIKE ", $where );

    return $where;
} 

将带引号的字符串与最终转义引号(或其他字符)匹配的子模式是:

'[^'\]*+(?s:\.[^'\]*)*+'

(请注意,要在正则表达式模式中计算文字反斜杠,必须对其进行转义,因为反斜杠是特殊字符)

所以在 php 字符串中(反斜杠需要再转义一次):

$pattern = "~'[^'\\]*+(?s:\\.[^'\\]*)*+'~";

有了这些信息,我想你可以自己构建模式了。

详情:

'        # a literal single quote
[^'\]*+ # zero or more characters that are not a single quote or a backslash
(?s:     # open a non-capture group with the s modifier (the dot can match newlines)
    \.      # an escaped character
    [^'\]*  
)*+      # repeat the group zero or more times
'