SED Match/Replace URL 和更新序列化数组计数

SED Match/Replace URL and Update Serialized Array Count

下面是来自 sql 转储文件的示例片段。此特定行包含 Wordpress PHP 序列化数组的 meta_value。在 dev.、test. 和 qc 中的数据库还原期间。环境 我正在使用 sed 将 URL 替换为相应的环境子域。

INSERT INTO `wp_postmeta`
    (`meta_id`,
     `post_id`,
     `meta_key`,
     `meta_value`)
VALUES
    (527,
     1951,
     'ut_parallax_image',
     'a:4:{
          s:17:\"background-image\";
          s:33:\"http://example.com/background.jpg\";
          s:23:\"mobile-background-image\";
          s:37:\"www.example.com/mobile-background.jpg\";
      }')
;

但是,我需要对其进行扩展以更正替换后序列化数组中的字符串长度。

sed -r -e "s/:\/\/(www\.)?${domain}/:\/\/\.${domain}/g" "/vagrant/repositories/apache/$domain/_sql/$(basename "$file")" > "/vagrant/repositories/apache/$domain/_sql/.$(basename "$file")"

开发人员的结果应如下所示:

INSERT INTO `wp_postmeta`
    (`meta_id`,
     `post_id`,
     `meta_key`,
     `meta_value`)
VALUES
    (527,
     1951,
     'ut_parallax_image',
     'a:4:{
          s:17:\"background-image\";
          s:37:\"http://dev.example.com/background.jpg\";
          s:23:\"mobile-background-image\";
          s:41:\"www.dev.example.com/mobile-background.jpg\";
      }')
;

除了 sed,我不想引入任何依赖项。

你的算法涉及算术。这使得 sed 成为一个糟糕的选择。请考虑 awk

考虑这个输入文件:

$ cat inputfile
  something...
  s:33:\"http://example.com/background.jpg\";
  s:37:\"www.example.com/mobile-background.jpg\";
  s:33:\"http://www.example.com/background.jpg\";
  more lines...

我相信这会满足您的要求:

$ awk -F'"' '/:\/\/(www[.])?example.com/ {sub("example.com", "dev.example.com"); n=length()-1; sub(/:[[:digit:]]+:/, ":" n ":")} 1' inputfile 
  something...
  s:37:\"http://dev.example.com/background.jpg\";
  s:37:\"www.example.com/mobile-background.jpg\";
  s:41:\"http://www.dev.example.com/background.jpg\";
  more lines...

WP-CLI 在搜索替换 http://wp-cli.org/commands/search-replace/ 期间处理序列化 PHP 数组。我想尝试原生的 shell 解决方案,但最终拥有 WP-CLI 是值得的。

这是您要求的示例文本文件(它是数据库导出文件)。

原文(https://www.example.com):

LOCK TABLES `wp_options` WRITE;
INSERT INTO `wp_options` VALUES (1,'siteurl','https://www.example.com','yes'),(18508,'optionsframework','a:48:{s:4:\"logo\";s:75:\"https://www.example.com/wp-content/uploads/2014/04/logo_imbrique_small3.png\";s:7:\"favicon\";s:62:\"https://www.example.com/wp-content/uploads/2017/04/favicon.ico\";}','yes')
/*!40000 ALTER TABLE `wp_options` ENABLE KEYS */;
UNLOCK TABLES;

需要结果(http://example.localhost):

LOCK TABLES `wp_options` WRITE;
INSERT INTO `wp_options` VALUES (1,'siteurl','http://example.localhost','yes'),(18508,'optionsframework','a:48:{s:4:\"logo\";s:76:\"http://example.localhost/wp-content/uploads/2014/04/logo_imbrique_small3.png\";s:7:\"favicon\";s:64:\"https://example.localhost/wp-content/uploads/2017/04/favicon.ico\";}','yes');
/*!40000 ALTER TABLE `wp_options` ENABLE KEYS */;
UNLOCK TABLES;

如你所见:

  • 同一行出现多次
  • 转义字符不计入长度数字(例如:“/”)
  • 有些事件前面没有 "s:" 长度数字(不需要替换,可以在 awk 之后用简单的 sed 完成)

提前致谢!

感谢@John1024。 @Fabio 和@Seth,我不确定性能,但这些代码在没有 wp-cli 的情况下工作:

localdomain=mylittlewordpress.local
maindomain=strongwordpress.site.ru
cat dump.sql | sed 's/;s:/;\ns:/g' | awk -F'"' '/s:.+'$maindomain'/ {sub("'$maindomain'", "'$localdomain'"); n=length()-1; sub(/:[[:digit:]]+:/, ":" n ":")} 1' | sed ':a;N;$!ba;s/;\ns:/;s:/g' | sed "s/$maindomain/$localdomain/g" | mysql -u$USER -p$PASS $DBNAME

PHP 序列化字符串由 ';s:' 分解为多行字符串,awk 通过@John1024 解决方案处理所有行。

cat dump.sql | sed 's/;s:/;\ns:/g'

将输出重定向到 awk

awk -F'"' '/^s:.+'$maindomain'/ {sub("'$maindomain'", "'$localdomain'"); n=length()-1; sub(/:[[:digit:]]+:/, ":" n ":")} 1'

处理完所有行后,多行内爆为一行(然后存在于原始 dump.sql 中)。谢谢@Zsolt

sed ':a;N;$!ba;s/;\ns:/;s:/g'

添加 sed 替换 wordpress 数据库中任何其他字符串的需要。

sed "s/$maindomain/$localdomain/g"

并载入主服务器数据库

... | mysql -u$USER -p$PASS $DBNAME