如何使PHP程序在输出中不以“被杀”结尾?

时间:2018-09-19 13:10:31

标签: php

我正在尝试使用PHP解析.log文件。我的程序始终以“ killed”消息结尾。我尝试在具有相同输入.log文件的两个不同服务器上运行我的PHP程序。

最终,我需要计算.log文件中某个模式的实例。该.log文件是一个文本文件,每行具有各种文本。每行都有一个连字符,用作字段分隔符。给定行上的破折号“-”右边的任何文本都可以打折,而不考虑。

我有一个名为“调用者”的递归函数。我尝试重新编写代码以不使用递归。我对这种方法有不同的疑问。

我尝试将输出保存到变量或新文件中。两种方法都没有给我带来明显的优势。我认为输出(根据我的逻辑节省模式)不会导致内存问题。

我在代码中有一个嵌套循环。对于.log文件的每一行,我正在从左到右检查每个字符以找到破折号“-”。

每次运行PHP程序时,dmesg命令都会显示如下一行:

  

UB 999的内存不足:OOM杀死进程950(php)的得分为0 ...

如何重新编写该代码,使其不以“被杀死”消息结尾?

(我的代码还没有计算出模式。我还没有准备好完成它。我只想进入中间步骤,它不以“ killed”一词结尾。)

这是我的代码:

<?php

$filea = "good.log";
$newf = fopen("new.txt", "w");
$file = fopen($filea, "r");

$charnum = 0;
$numlines = 0;
$temp = fopen($filea, "r");
while(!feof($temp)){
  $line = fgets($temp);
  $numlines++;
}
fclose($temp);

function caller($newf, $fileline, $charnum){
  if ($fileline[$charnum] == '-') {
    $x = $charnum;
    $stringx = "";
    for ($h = 0; $h < $x; $h++){
      $stringx = $stringx.$fileline[$h];
     }
    fwrite($newf, $stringx);
    fwrite($newf, "\n");
    echo $stringx;
   }
  else {
    $charnum = $charnum + 1;
    caller($newf, $fileline, $charnum);
  }
}
for ($k = 0; $k < $numlines; $k = $k++) {
  $fileline = fgets($file);
  $charnum = 0;
  caller($newf, $fileline, $charnum);
  }
fclose($newf);
fclose($file);
?>

3 个答案:

答案 0 :(得分:1)

大概您的一条日志行不包含"-",因此您的函数可以无限递归。

删除递归并修复错误将给出:

function caller($newf, $fileline, $charnum){
  $len = strlen($fileline);
  for ( $i = $charnum; $i < $len; $i++ )
  {
    if ($fileline[$i] == '-') {
      $x = $i;
      $stringx = "";
      for ($h = 0; $h < $x; $h++){
        $stringx = $stringx.$fileline[$h];
       }
      fwrite($newf, $stringx);
      fwrite($newf, "\n");
      echo $stringx;
      return;
     }
  }
}

一种更简单的方法是使用内置的PHP函数strpossubstr

function caller($newf, $fileline){
  $pos = strpos($fileline, "-");
  if ( $pos !== FALSE )
  {
    $stringx = substr( $fileline, 0, $pos );
    fwrite($newf, $stringx);
    fwrite($newf, "\n");
    echo $stringx;
  }
}

顺便说一句,对行数进行计数的初始循环似乎没有必要?您可以这样做:

while(!feof($file)){
  $fileline = fgets($file);
  $charnum = 0;
  caller($newf, $fileline, $charnum);
  }

答案 1 :(得分:1)

因此,您的代码实际执行的操作是遍历日志文件并计算while循环中的行数。 (无需每次覆盖$line。)

然后在您的for循环中,您一次向函数caller传递一行,并指示charnum 0。

在函数中,您检查charnum处的字符是否为-,如果是,则继续执行操作。但是,如果不是-,则继续下一个字符。 ...您的问题是您通过递归调用caller来做到这一点!因此,对于该行中的每个字符,您都会在调用堆栈上放置一个新的函数调用。不要这样最好在caller函数中放置一个for循环,以使charnum每次递增,并在最终找到break时使用-脱离for循环。那应该可以解决您的问题。

答案 2 :(得分:0)

如果您只是想将每行的部分放在短划线的左侧,则可以在一行中完成所有操作:

preg_match_all('/^([^-\n])\-/m', file_get_contents('good.log'), $matches);

此后,$matches[0]将包含一个匹配的术语列表(包括破折号),而$matches[1]将包含相同的列表而不包含破折号。例如,给定:

one two - three - four
no dash on this line
five - six
seven - eight

然后,$matches[1]将是一个包含以下内容的数组:one twofiveseven