【问题标题】:Use AWK to safely search and replace URLs in Wordpress SQL-Dump使用 AWK 在 Wordpress SQL-Dump 中安全地搜索和替换 URL
【发布时间】:2018-01-29 13:54:10
【问题描述】:

我正在开发一个网络工具,以将 Wordpress 安装镜像到开发系统中。

我们的目标是拥有一个用于生产的 Live 系统和一个用于测试的开发系统。然后,网络工具在这些系统之间提供一键式同步。 每个系统都是独立的,有自己的 webroot、数据库和 url。

我在数据库转储中遇到问题,我必须在其中搜索对源的所有引用并将它们替换为目标的 URL(例如:“www.example.com”->“www-dev. example.com")。

我需要做的是:

  1. 查找所有出现的 URL 并将其替换为新的。

  2. 如果匹配也匹配序列化字符串的格式,则应设置字段分隔符,并重新加载匹配,以便在数组中设置实际长度。

在第一次尝试中,我尝试使用如下所示的“sed”命令解决此问题:sed -i.orig 's/360\.example\.com/360-dev\.my\.example\.dev/g'。 这不起作用,因为转储中包含包含 url 的序列化数组。 sed 命令不利于更新序列化数组的字符串长度指示符。

我最近的尝试是按照here 的建议使用awk,因为它能够进行算术运算。

我的awk 脚​​本如下所示:

/360[.]example[.]com/ {
    sub("360.example.com", "360-dev.my.example.dev");
    if ($0 ~ /s:[[:digit:]]+:["](http[s]?:\/\/)?360[.]example[.]com["]/){
        FS="\"";
        $0=$0;
        n=length($2)-1;
        sub(/:[[:digit:]]+:/, ":" n ":");
    }
} 1

我的脚本中似乎有一些错误,我找不到。它不会替换所有出现的 url 并完全跳过 length-indicator-update。

如何修复我的脚本以实现我想做的事情?

编辑:(添加输入/输出示例) Databasedump 由整个 wordpress 数据库组成,每个表和记录都有 CREATE TABLE IF NOT EXISTSINSERT 语句。

正常(未序列化)发生:

(36, 'home', 'http://360.example.com/blogname', 'yes'),

应该导致:

(36, 'home', 'http://360-dev.my.example.dev/blogname', 'yes'),

序列化发生:

(404, 'wp-maintenance-mode', 'a:21:{s:6:"active";i:1;s:4:"time";i:0;s:4:"link";i:1;s:7:"support";i:0;s:10:"admin_link";i:1;s:7:"rewrite";s:0:"";s:6:"notice";i:1;s:4:"unit";i:1;s:5:"theme";i:0;s:8:"styleurl";s:69:"http://360.example.com/wp-content/themes/blogname/css/maintenance.css";s:5:"index";i:0;s:5:"title";s:0:"";s:6:"header";s:0:"";s:7:"heading";s:0:"";s:4:"text";s:12:"Example Text";s:7:"exclude";a:1:{i:0;s:0:"";}s:6:"bypass";i:0;s:4:"role";a:1:{i:0;s:13:"administrator";}s:13:"role_frontend";a:1:{i:0;s:13:"administrator";}s:5:"radio";i:0;s:4:"date";s:0:"";}', 'yes'),

应该导致:

(404, 'wp-maintenance-mode', 'a:21:{s:6:"active";i:1;s:4:"time";i:0;s:4:"link";i:1;s:7:"support";i:0;s:10:"admin_link";i:1;s:7:"rewrite";s:0:"";s:6:"notice";i:1;s:4:"unit";i:1;s:5:"theme";i:0;s:8:"styleurl";s:76:"http://360-dev.my.example.dev/wp-content/themes/blogname/css/maintenance.css";s:5:"index";i:0;s:5:"title";s:0:"";s:6:"header";s:0:"";s:7:"heading";s:0:"";s:4:"text";s:12:"Example Text";s:7:"exclude";a:1:{i:0;s:0:"";}s:6:"bypass";i:0;s:4:"role";a:1:{i:0;s:13:"administrator";}s:13:"role_frontend";a:1:{i:0;s:13:"administrator";}s:5:"radio";i:0;s:4:"date";s:0:"";}', 'yes'),

编辑 2: 现在使用wp-cli 来完成搜索和替换的任务。 我有一个多站点设置,其中的博客编号为 (2,3,9)。 执行wp search-replace --url=360.example.com '360.example.com' '360-dev.my.example.dev' 会导致错误,告诉我找不到单站点表(wp_redirection_items 和 wp_redirection_groups)。 这是真的,因为它们确实不存在,而是针对每个博客(例如:wp_2_redirection_items 等)。此错误会导致 s&r 中出现超过 9000 次遗漏。可以用wp search-replace --url=360.example.com '360.example.com' '360-dev.my.example.com' wp_* 替换所有内容。但它仍然会抛出错误。

【问题讨论】:

  • 你能用wp-cli吗?它可以很容易地做到这一点:developer.wordpress.org/cli/commands/search-replace
  • 实际上我已经在使用 wp-cli,但确实监督了该命令...抱歉打扰您!如果满足我的需要,我会尝试并及时更新! :)
  • 这个命令已经很有帮助了。但它会抛出一个错误,并告诉我它找不到表“wp_redirection_items”用于“wp_redirection_groups”上的 INNER JOIN。我在这里有一个多站点设置,所以这些表实际上不存在,但是“wp_2_redirection_items”等等......有什么想法可以解决这个问题吗?

标签: wordpress search awk replace command-line


【解决方案1】:

正如@archimiro 所建议的,现在任务由wp-cli 完成。 但由于我也有一个多站点设置,这会导致一些错误,我必须找出完整数据库搜索替换任务的命令。

最后的命令: wp search-replace --url=360.example.com '360.example.com' '360-dev.my.example.dev' wp_*。 如果没有明确告诉 wp-cli 在所有 (wp_*) 表中搜索和替换,它将在抛出“未找到表”错误时停止。

【讨论】:

    【解决方案2】:

    也不是 awk 或 wpcli,但这是我编写的一个似乎运行良好的 php 函数。

        function snr($search, $replace, $inputfile, $outputfile){
        $sql = file_get_contents($inputfile);
        $sql1 = str_replace($search,$replace,$sql);
        file_put_contents($outputfile,$sql1);
        $serstrings = preg_split("/(?<=[{;])s:/",$sql1);
    
        foreach($serstrings as $i=>$serstring) {
            if (!!strpos($serstring, $replace)){
            $justString = str_replace("\\","",str_replace("\\\\","j",explode('\\";',explode(':\\"',$serstring)[1])[0]));
            $correct = strlen($justString);
            $serstrings[$i] = preg_replace('/^\d+/',$correct, $serstrings[$i]);
             } 
        }
        file_put_contents($outputfile,implode("s:",$serstrings));
    }
    

    【讨论】:

      【解决方案3】:

      我过去曾成功使用过它:

      sed 's|360\.example\.com|360-dev\.my\.example\.dev|g' com.sql > local.sql
      

      编辑:抱歉不是 awk,但 wp-cli 也不是。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-23
        • 1970-01-01
        • 2015-02-15
        • 2011-02-04
        相关资源
        最近更新 更多