MySQL 复杂的 REGEXP 查找和替换

问题描述 投票:0回答:2

我想在 WordPress 数据库上运行正则表达式查找和替换,特别是在 wp_posts 表中的 post_content 列中。我有几个附属 URL 分散在 post_content 列的文本中,我需要将它们替换为新的附属 URL。问题是当前的 URL 有多个参数,这些参数可能会根据 URL 的不同而有所不同,而且它们的顺序并不总是相同。所有 URL id 中唯一一致的参数是 store_id 参数。

当前 URL 示例:

https://www.affialite.com/redirect.php?tt=el&store_id=this_is_the_store_id&param1=this_is_param_1&url=https://redirect_the_visitor_to_this_url.com&c_id=id_of_the_campaign

查找/替换操作后的外观示例:

https://newaffiliate.net/c/1234/5678/9012?campaign=id_of_the_campaign&u=https://redirect_the_visitor_to_this_url.com

查询必须找到联属链接,将 URL 的第一部分替换为新的联属 url,捕获参数 url 的值并将其与新的 u 参数匹配,并捕获 c_id 的值参数并将其与新的 campaign 参数相匹配。

除了常规的 CRUD 操作之外,我对 mysql 有接近零的经验,所以我使用 ChatGPT 来帮助我为此构建一个查询。我得到的最接近的是下面的一个,但生成的 URL 在所有错误的位置都有参数。

UPDATE wp_posts
SET post_content =
    REGEXP_REPLACE(
        post_content,
        'https:\/\/www\.affiliate\.com\/redirect\.php\?(?:.*?&|.*?&)(store_id=this_is_the_store_id)(?:&.*?|&)(.*?)',
        CONCAT(
            'https://newaffiliate.net/c/1234/5678/9012?',
            'campaign=',
            REGEXP_SUBSTR(
                REGEXP_SUBSTR(CONCAT('&', '\\2', '&'), '&c_id=([^&]+)'),
                '[^=]+$'
            ),
            '&u=',
            REGEXP_SUBSTR(
                REGEXP_SUBSTR(CONCAT('&', '\\2', '&'), '&url=([^&]+)'),
                '[^=]+$'
            )
        )
    )
WHERE post_content REGEXP 'https:\/\/www\.affiliate\.com\/click\.php\?(?:.*?&|.*?&)(store_id=this_is_the_store_id)(?:&.*?|&)(.*?)';

以下是“错误”结果 URL 的示例: https://newaffiliate.com?campaing=&u=param1=this_is_param_1&url=https://redirect_the_visitor_to_this_url.com&c_id=id_of_the_campaign

对查询有什么问题有什么见解吗?非常感谢任何帮助。

谢谢大家。

mysql regex replace find
2个回答
0
投票

我注意到 ChatGPT 出错的一件事是,反向引用的 MySQL 语法类似于

$1

$2
,而不是
\1
\2
我在 MySQL 8.0.36 中测试了以下内容。我进行了替换,并且还包含了字面预期的 URL,因此我们可以并排比较它们。

CREATE TABLE wp_posts ( post_content text ); INSERT INTO wp_posts VALUES ('https://www.affiliate.com/redirect.php?tt=el&store_id=this_is_the_store_id&param1=this_is_param_1&url=https://redirect_the_visitor_to_this_url.com&c_id=id_of_the_campaign'); SELECT REGEXP_REPLACE(post_content, 'https://www.affiliate.com/redirect.php\\?.*url=([^&]*).*c_id=([^&]*)', 'https://newaffiliate.net/c/1234/5678/9012?campaign=$2&u=$1') AS new_url, 'https://newaffiliate.net/c/1234/5678/9012?campaign=id_of_the_campaign&u=https://redirect_the_visitor_to_this_url.com' AS intended FROM wp_posts\G

输出:

*************************** 1. row *************************** new_url: https://newaffiliate.net/c/1234/5678/9012?campaign=id_of_the_campaign&u=https://redirect_the_visitor_to_this_url.com intended: https://newaffiliate.net/c/1234/5678/9012?campaign=id_of_the_campaign&u=https://redirect_the_visitor_to_this_url.com

您说 URL 中的参数并不总是按相同的顺序排列。上述解决方案仅支持一种顺序,其中 
url

参数位于

c_id
参数之前。该解决方案很容易修改,以处理参数按其他顺序的情况。
REGEXP_REPLACE(post_content,
   'https://www.affiliate.com/redirect.php\\?.*c_id=([^&]*).*url=([^&]*)',
   'https://newaffiliate.net/c/1234/5678/9012?campaign=$2&u=$1')

这可能需要分两遍运行 UPDATE,但考虑到它允许两个语句变得更简单,它仍然是一个胜利。


0
投票
any

顺序处理参数。例如: CREATE TABLE wp_posts (post_content text); INSERT INTO wp_posts VALUES ('https://www.affiliate.com/redirect.php?tt=el&store_id=this_is_the_store_id&param1=this_is_param_1&url=https://redirect_the_visitor_to_this_url.com&c_id=id_of_the_campaign'), ('https://www.affiliate.com/redirect.php?tt=el&store_id=this_is_the_store_id&c_id=id_of_the_campaign&param1=this_is_param_1&url=https://redirect_the_visitor_to_this_url.com') ('https://www.affiliate.com/redirect.php?tt=el&store_id=this_is_another_store_id&c_id=id_of_the_campaign&param1=this_is_param_1&url=https://redirect_the_visitor_to_this_url.com') ; UPDATE wp_posts SET post_content = REGEXP_REPLACE( post_content, 'https://www\\.affiliate\\.com/redirect\\.php\\?(?=.*\\bstore_id=this_is_the_store_id\\b)(?=.*\\bc_id=([^&]*))(?=.*\\burl=([^&]*)).*', 'https://newaffiliate.net/c/1234/5678/9012?campaign=$1&u=$2' ) SELECT * FROM wp_posts

输出:

post_content https://newaffiliate.net/c/1234/5678/9012?campaign=id_of_the_campaign&u=https://redirect_the_visitor_to_this_url.com https://newaffiliate.net/c/1234/5678/9012?campaign=id_of_the_campaign&u=https://redirect_the_visitor_to_this_url.com https://www.affiliate.com/redirect.php?tt=el&store_id=this_is_another_store_id&c_id=id_of_the_campaign&param1=this_is_param_1&url=https://redirect_the_visitor_to_this_url.com

dbfiddle.uk

上进行演示 备注:

您不需要
    WHERE
  • 上的
    UPDATE
    子句;如果正则表达式不匹配,则不会发生替换。
    你不需要逃避
  • /
  • ;但你应该转义
    .
    因为它可以匹配任何字符
  • \b
  • c_id
    前面使用
    url
    更安全,这样它们就不会匹配(例如)
    ac_id
    curl
    要转义字符串中需要 
  • \\
  • 的值,因为第一个
    \
    被字符串解析吸收。
    
        
© www.soinside.com 2019 - 2024. All rights reserved.