4

我正在使用 preg_match_all 搜索我正在读入的文件。该文件包含以下格式的许多行,我正在提取标签之间的数字;

<float_array id="asdfasd_positions-array" count="6">1 2 3 4 5 6</float_array>

我正在使用 preg_match_all 并且它运行良好 - 除了它通过文件走得太远然后似乎停止了。

preg_match_all("/\<float_array id\=\".+?positions.+?\" count\=\".+?\"\>(.+?)\<\/float_array\>/",$file, $results);

该文件有 90,000 行,大小约为 8MB。我正在编辑提取的字符串中的每三个数字,并使用 str_replace 将其编辑回文件中。然后再次写入该文件。在此处查看完整脚本;

http://pastie.org/4300537

该脚本成功地替换了大约一半的条目,并且对文件的后半部分没有做任何事情。我什至从文件的较高位置复制了一个成功编辑的行并进一步向下粘贴......并且它没有在文件中进一步编辑。就好像数组已满但 memory_limit 设置为 500M。

有任何想法吗?

编辑:找到解决方案

我发现了问题——在某些情况下,标签之间的字符串太大而被跳过。我在 PHP 中找到了限制。pcre.backtrack_limit 设置为 100000 并且某些字符串大于此值。所以我使用以下行在 .htaccess 文件中增加了它,它现在可以工作了。

php_value pcre.backtrack_limit 5000000

4

2 回答 2

2

如果内存是一个问题而不是执行时间限制,那么使用慢速解决方案(逐行)>>

$fi = fopen("data.txt",  "r");
$fo = fopen('data2.txt', 'w');
while (!feof($fi)) {
  $line = fgets($fi);

  # regex stuff here

  fwrite($fo, $line);
}
fclose($fi);
fclose($fo);
于 2012-07-22T14:27:31.493 回答
0

您可能会考虑使用像这样的简单解析器来解析您的文本文件>>

$fi = fopen("data.txt",  "r");
$fo = fopen('data2.txt', 'w');
$status = 0;
do {
  $data = stream_get_line($fi, PHP_INT_MAX, ">");
  if ($status == 1) {
    preg_match("/(.*)<\/float_array$/", $data, $m);
    $status--;
    if (sizeof($m) != 0) {
      fwrite($fo, $m[1] . "\n");
      continue;
    }
  }
  if ($status == 0) {
    preg_match("/<float_array[^>]*?\bid\s*=\s*[\"'][^\"']*?positions[^\"']*?[\"'][^>]*?\bcount\s*\=[^>]*?$/", $data, $m);
    if (sizeof($m) > 0) {
      $status++;
    }
  }
} while (!feof($fi));
fclose($fi);
fclose($fo);
于 2012-07-22T18:12:26.677 回答