• 喜欢前端以及PHP的朋友们可以加PHP同好会QQ群 点击加入qq群
  • 最近在写一个项目---"小A微信托管平台",大家可以去帮忙测试一下!功能在不断完善中,敬请关注!点击进入
  • 本站使用了PHP8.1与HTTP2.0协议,速度简直超级快有木有?

使用python (正则) 替换php序列化内的字符串

后端 Mr.Adam 4年前 (2020-11-17) 1454次浏览 已收录 0个评论

使用 python (正则) 替换 php 序列化内的字符串

使用 python (正则) 替换 php 序列化内的字符串

在 PHP 中,序列化用于存储或传递 PHP 的值的过程中,同时不丢失其类型和结构。
序列化函数如下:
string serialize ( mixed $value )

php 的序列化是将变量(数字,字符,数组,对象)转为字符串的函数,其格式如下:

class CC {
    public $data;
    private $pass;

    public function __construct($data, $pass)
    {
        $this->data = $data;
        $this->pass = $pass;
    }
}
$number = 34;
$str = 'uusama';
$bool = true;
$null = NULL;
$arr = array('a' => 1, 'b' => 2);
$cc = new CC('uu', true);

var_dump(serialize($number));
var_dump(serialize($str));
var_dump(serialize($bool));
var_dump(serialize($null));
var_dump(serialize($arr));
var_dump(serialize($cc));

输出结果:

string(5) "i:34;"
string(13) "s:6:"uusama";"
string(4) "b:1;"
string(2) "N;"
string(30) "a:2:{s:1:"a";i:1;s:1:"b";i:2;}"
string(52) "O:2:"CC":2:{s:4:"data";s:2:"uu";s:8:" CC pass";b:1;}"

字符串的格式为:
s:{0-9}:”…”;
前面的数字正好是后面字符串的长度(strlen,而不是 mb_strlen),如果字符串内容改变了,而字符前的数字对不上的时候,反序列化的时候会报错
wordpress 自身会将很多变量函数之类,甚至是 html,css,js 代码都使用 serialize 序列化成字符串存入 mysql 中
导致的一个问题就是如果我们要更换网站域名或者其他配置信息的时候,不能直接更改内容,造成很多不便
网上查了很多资料也没有解决这个的方法,无非是用 php 反序列化成相应的字符串,数组,对象,然后更改值之后,再序列化成字符串,这样面对小范围的数据修改是可行的,但是如果面对大数据量的时候就有点不够看了
如果能有个正则,一下子替换整个 sql 文件就完美了,思考良久,于是有了如下方法,仅供大家参考
在这里分享一个用 python 写的使用正则替换序列化后字符串内容的方法
代码如下:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import io
import re
import os
import sys
import time

if len(sys.argv) != 5:
	print '\033[1;31;40m'
	print '*' * 50
	print '参数不全'
	print '*' * 50
	exit()
old_str = sys.argv[3]
new_str = sys.argv[4]
sql_file = sys.argv[1]
new_file = sys.argv[2]


if not os.path.isfile(sql_file):
	print '\033[1;31;40m'
	print '*' * 50
	print 'sql 文件不存在'
	print '*' * 50
	exit()

old_str_arr = old_str.split("|")
if len(old_str_arr) > 1:
	pattern = "("
	for domain in old_str_arr:
		if domain[-2:] == "co":
			pattern += "(?<!.)"+domain+"(?!m)|"
		else:
			pattern += "(?<!.)"+domain+"|"
	pattern = pattern[:-1]
	pattern += ")"
else:
	pattern = "(?<!.)"+old_str_arr[0]
pattern = pattern.replace('.','\.')
pattern = pattern.replace('-','\-')
pattern = pattern.replace('_','\_')

if os.path.isfile(new_file):
	os.system("echo > "+new_file)

def change_domain(match):
	old = match.group(2)
	old_len = match.group(1)
	new = re.sub(pattern,new_str,old,0,re.I)
	new_len = len(new)
	return "s:"+str(new_len)+":\""+new+'";'

start_time = time.time()

n_file = open(new_file,"a")
n = 0
with open(sql_file,"r") as f:
	while True:
		line = f.readline()
		new_line = re.sub(r"(?:s\:)(\d+)(?:\:\")([\s\S]*?)(?:\"\;)",change_domain,line,0,re.I)
		new_line = re.sub(pattern,new_str,new_line,0,re.I)
		n_file.write(new_line)
		n+=1;
		print "已替换"+str(n)+"行"
		if not line:
			break
n_file.close()
end_time = time.time()
cut_time = int(end_time-start_time)
fen = round(cut_time/60,2)
print "替换成功!共用时"+str(fen)+"分钟!"

使用方式:

#将 old.sql 文件里的 a.com,b.com,a.co 统一替换为 abc.cn
change_domain.py old.sql new.sql 'a.com|b.com|a.co' 'abc.cn'

该脚本的核心就是 re.sub 可以使用一个回调函数来修改为需要复杂处理的字符串,而在回调函数中还可以使用正则去替换我们需要替换的字符串,相同的方式 php,js,java,shell 等其他语言也可以做到
:cool:


小 A 空间 , 版权所有丨如未注明转载 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明使用 python (正则) 替换 php 序列化内的字符串
喜欢 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址