PHP preg_replace日期时间值增加

时间:2014-05-12 15:46:34

标签: php file parsing date preg-replace

我需要在一个可能很大的SQL转储文件(~2-3MB)内找到并替换所有日期实例,其实际值随给定值的增加而增加。这是必需的,因为我的公司使用此SQL转储文件来部署特定软件的演示,并且日期需要转换为正确适合演示可用的时间段。

这是一个小提取物,作为一个例子:

  

INSERT INTO ordiniidid_fornitoredataoggetti_ordine,   data_consegnacontrollodata_consegna_prevista,   resp_controlloDDTnr_DDTiknow_iddocuspedizione,   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

因此,我需要逐步详细说明输入。问题是,如果我将输入文件拆分为固定大小的块,我可能会碰巧中止一个日期(因此不会将其推到所需的值之前)。 这个问题的好方法是什么? (除了手动将输入文件预分割成几个较小的文件)。谢谢你的帮助。

2 个答案:

答案 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

Also take a look at this