我有来自外部来源的PHP serialize()
'字符串:
s:4:"0.00";s:4:"type";s:5:"price";s:3:"$20";s:12:"Foo "Bar" Baz";s:1:"y";
我需要将"Bar"
替换为"Bar"
才能成功unserialize()
。
如何使用preg_replace()
来完成此任务?
我尝试了(?<!s:\d{1,4}:)("[0-9a-zA-Z ]+")
,但是PHP抛出了后视错误: lookbehind断言在偏移量14处不是固定长度
更新:这是我编写的虚拟字符串。我错误地计算了字符...可以安全地假设计数是正确的......字符串应该是:
s:4:"0.00";s:4:"type";s:5:"price";s:3:"$20";s:13:"Foo "Bar" Baz";s:1:"y";
答案 0 :(得分:3)
如果您的字符串可以反序列化,请执行此操作,然后使用htmlspecialchars
将引号(以及<
和>
)替换为HTML实体。如果您要使用str_replace
替换仅引号。
代码中的问题是不有引号的事实!实际上,转义引号并不能解决你的问题。
让我们看一下您所拥有的序列化字符串的表示形式:s:12:"Foo "Bar" Baz";
这意味着你有一个包含12
字符的 s tring - 引号根本不需要在那里转义。
现在您的序列化数据有什么问题?
s:12:"Foo "Bar" Baz";
1234567890123
如您所见,您有13个字符,而解析器只需要12个字符。这就是为什么你不能反序化它的原因!但是,这意味着您需要将12
更改为13
才能解决问题。
这究竟意味着什么? 无法使用正则表达式修复数据!您实际需要做的是修复向您发送无效数据的来源!
答案 1 :(得分:1)
$string = preg_replace_callback('/(s:\d+:\")(.*?)(\";)/i', function($matches){
return $matches[1] . htmlspecialchars($matches[2], ENT_QUOTES) . $matches[3];
}, $string);
(如果您的字符串中有分号后面的分号,则会失败,例如Foo "Bar"; Foo
)
@ThiefMaster是对的。尝试完全纠正字符串:
$keys = 0;
$string = preg_replace_callback('/s:(\d+):\"(.*?)\";/i',
function($matches) use(&$keys){
return sprintf('i:%d;s:%d:"%s";', ++$keys, strlen($matches[2]), $matches[2]);
}, $string);
$string = sprintf('a:%d:{%s}', $keys, $string);
$result = unserialize($string);
我把它包装在一个数组中,因为如果你反序列化你所拥有的,你只能得到第一个元素的值......
答案 2 :(得分:-1)
preg_replace('|( "[0-9A-Z]+" )|ei', " stripslashes(htmlentities('$1')) ", $str)