我需要在一个可能很大的SQL转储文件(~2-3MB)内找到并替换所有日期实例,其实际值随给定值的增加而增加。这是必需的,因为我的公司使用此SQL转储文件来部署特定软件的演示,并且日期需要转换为正确适合演示可用的时间段。
这是一个小提取物,作为一个例子:
INSERT INTO
ordini
(id
,id_fornitore
,data
,oggetti_ordine
,data_consegna
,controllo
,data_consegna_prevista
,resp_controllo
,DDT
,nr_DDT
,iknow_iddocu
,spedizione
,pagamento
)价值观(10,204,' 2011-11-29 ','Palline gialle ## Palline rosse ## Palline verdi ##§§1000## 200 ## 360 ##§§12€## 10€## 11.5€##', ' 2012-12-29 ',0,' 2011-12-05 ',0,'','',0,'A mano','30 gg 。'),(13, 204,' 2011-11-30 ','Palline verdi ##§§12##§§5.750##',' 2013-04-23 ',0 , ' 1970-01-01 ',0,'','',0,'',''),(14,204,' 2011-11-30 ','Palline verdi ## Palline rosse ##§§12## 22 ##§§5.750## 5.750 ##',' 2013-02-22 ',0, ' 2011-12-31 ',0,'','',0,'A mano','Ri.Ba。 30 gg。');
如您所见,文件中的所有日期都是mysql YYYY-MM-DD DATETIME格式,如:'2013-03-12'。有时候,其中一些可能还包括日期之后的时间,但这与我的需求无关,时间应保持不变。
我最终安排了这个简单的脚本:
<?php
$push_period = "30";
print "<h1>Parsing file...</h1>";
print "<h2>Pushing dates ahead of {$push_period} days.</h2>";
$file=implode("\n",file('db.sql'));
print($file);
preg_match_all('@(\d\d\d\d)-(\d\d)-(\d\d)@', $file, $match, PREG_OFFSET_CAPTURE);
print "<br /><br />";
print "<table border=1 align='center'>";
print "<th colspan='3'><b>Dates moved {$push_period} days ahead</b></th>";
$array_new_dates = array();
foreach ($match[0] as $occurrence) {
print "<tr><td>";
print "<pre>";
print_r($occurrence);
print "</pre>";
print "</td><td width='40' align='center'>";
print "=>";
print "</td><td>";
print "<pre>";
$temp_array = array();
$modified_value = date('Y-m-d', strtotime($occurrence[0] . " +".$push_period." days"));
$temp_array[0] = $modified_value;
$temp_array[1] = $occurrence[1];
$array_new_dates[] = $temp_array;
print_r($temp_array);
print "</pre>";
print "</td></tr>";
$file = substr_replace($file, $modified_value, $occurrence[1], 10);
}
print "</table>";
print($file);
$file = str_replace("\n", "", $file);
$fp=fopen('updated_db.sql','w');
// Dumping updated file
fwrite($fp,$file,strlen($file));
?>
现在,我的问题是,如果我使用大文件运行此脚本,我可以预见会出现此错误:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 64 bytes) in /srv/www/htdocs/mysoftware_dev/date_replacer.php on line 10
因此,我需要逐步详细说明输入。问题是,如果我将输入文件拆分为固定大小的块,我可能会碰巧中止一个日期(因此不会将其推到所需的值之前)。 这个问题的好方法是什么? (除了手动将输入文件预分割成几个较小的文件)。谢谢你的帮助。
答案 0 :(得分:3)
这可以通过preg_replace_callback()
调用更简单,它允许您使用回调函数对匹配执行逻辑:
$string = ''; // Data from file
$string = preg_replace_callback(
'/\d{4}-\d{2}-\d{2}/',
function($matches) {
$date = new DateTime(reset($matches));
$oneDay = new DateInterval('P1D');
$date->add($oneDay);
return $date->format('Y-m-d');
},
$string
);
注意我是如何调整你的Regex的,并使用{}
指定了多少位并删除了捕获组。在使用原始DateTime
返回日期之前,我们使用PHP的::add()
类,然后使用DateInterval
::format()
作为值。
如果你还有记忆问题,我也会接受@ NietTheDarkAbsol的建议并查看fgets()
。但是,我清理过的逻辑会减少内存使用量(因为你不会将所有匹配存储在一个变量中并逐个循环遍历它们。)
答案 1 :(得分:0)
我想你会根据要求使用这个脚本,而不是每天都使用。也许最简单的解决方案是增加内存限制,目前128MB。
如果您的脚本确实能够正常运行,我没有尝试过,但是在PHP脚本中尝试增加内存限制:
ini_set("memory_limit","512M");
或 php.ini 中的这个:
memory_limit = 512M