我知道这是一个老问题,但我想迟到总比没有好。我最近遇到了这个问题,在继承了一个对序列化数据执行了查找/替换的数据库之后。经过几个小时的研究,我发现这是因为字符串计数关闭了。不幸的是,有很多数据有很多转义和换行符,在某些情况下我不知道如何计算,而且我有很多数据,我需要一些自动化的东西。
一路上,我偶然发现了这个问题,Benubird 的帖子帮助我走上了正确的道路。他的示例代码不适用于复杂数据的生产使用,包含大量特殊字符和 HTML,嵌套非常深,并且不能正确处理某些转义字符和编码。因此,我对其进行了一些修改,并花费了无数个小时来解决其他错误,以使我的版本“修复”序列化数据。
// do some DB query here
while($res = db_fetch($qry)){
$str = $res->data;
$sCount=1; // don't try to count manually, which can be inaccurate; let serialize do its thing
$newstring = unserialize($str);
if(!$newstring) {
preg_match_all('/s:([0-9]+):"(.*?)"(?=;)/su',$str,$m);
# preg_match_all("/s:([0-9]+):(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\")(?=;)/u",$str,$m); // alternate: almost works but leave quotes in $m[2] output
# print_r($m); exit;
foreach($m[1] as $k => $len) {
/*** Possibly specific to my case: Spyropress Builder in WordPress ***/
$m_clean = str_replace('\"','"',$m[2][$k]); // convert escaped double quotes so that HTML will render properly
// if newline is present, it will output directly in the HTML
// nl2br won't work here (must find literally; not with double quotes!)
$m_clean = str_replace('\n', '<br />', $m_clean);
$m_clean = nl2br($m_clean); // but we DO need to convert actual newlines also
/*********************************************************************/
if($sCount){
$m_new = $m[0][$k].';'; // we must account for the missing semi-colon not captured in regex!
// NOTE: If we don't flush the buffers, things like <img src="http://whatever" can be replaced with <img src="//whatever" and break the serialize count!!!
ob_end_flush(); // not sure why this is necessary but cost me 5 hours!!
$m_ser = serialize($m_clean);
if($m_new != $m_ser) {
print "Replacing: $m_new\n";
print "With: $m_ser\n";
$str = str_replace($m_new, $m_ser, $str);
}
}
else{
$m_len = (strlen($m[2][$k]) - substr_count($m[2][$k],'\n'));
if($len != $m_len) {
$newstr='s:'.$m_len.':"'.$m[2][$k].'"';
echo "Replacing: {$m[0][$k]}\n";
echo "With: $newstr\n\n";
$str = str_replace($m_new, $newstr, $str);
}
}
}
print_r($str); // this is your FIXED serialized data!! Yay!
}
}
关于我的更改的一些令人讨厌的解释:
- 我发现尝试以 Benubird 的代码为基础进行计数对于大型数据集来说太不准确了,所以我最终只使用序列化来确保计数是准确的。
- 我避免了 try/catch,因为在我的情况下,try 会成功,但只是返回一个空字符串。因此,我改为检查空数据。
- 我尝试了许多正则表达式,但只有 Benubird 上的一个 mod 可以准确处理所有情况。具体来说,我必须修改检查“;”的部分 因为它会在 CSS 上匹配,例如 "width:100%; height:25px;" 并打破了输出。所以,我使用了积极的前瞻来匹配“;” 在双引号集之外。
- 我的案例有很多换行符、HTML 和转义的双引号,所以我必须添加一个块来清理它们。
- 有一些奇怪的情况,数据会被正则表达式错误地替换,然后序列化也会错误地计算它。我在任何网站上都找不到任何帮助解决此问题的方法,最后认为它可能与缓存或类似的东西有关,并尝试刷新输出缓冲区(ob_end_flush()),这很有效,谢天谢地!
希望这对某人有所帮助...花了我将近 20 个小时,包括研究和处理奇怪的问题!:)