我想在 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
谢谢大家。
我注意到 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,但考虑到它允许两个语句变得更简单,它仍然是一个胜利。
顺序处理参数。例如:
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
要转义字符串中需要 \\
\
被字符串解析吸收。