【问题标题】:Use explode in a generator function to iterate over a long string in PHP在生成器函数中使用explode来迭代PHP中的长字符串
【发布时间】:2018-10-15 06:34:44
【问题描述】:

我正在使用 PHP 函数来解析一个很长的字符串(shell_exec 命令的输出)。目前,该功能如下所示,并且工作正常。

 /**
 * @param string $result Output of shell command
 * @return array $lines each line of output in array
 */
public function getLines($result)
{
    $lines = [];
    $expl = explode(PHP_EOL, $result);
    foreach ($expl as $line) {
         $lines[] = $this->funcFormatLine($line);
    }
    return $lines;
}

现在,我开始使用 generators in PHP,该函数看起来是重构使用它的好用例,因为爆炸输出数组很大并且会消耗一些内存。

我想要什么:

/**
 * @param string $result Output of shell command
 * @return string $line one line of output until end_of_line
 */
public function getLines($result)
{
    $line = fancy_func_to_get_all_before_end_of_line_without_array(PHP_EOL, $result);
    yield $line;
}

//somewhere in the function    
foreach (getLines($result) as $line) {
    doThings($this->funcFormatLine($line));
}

在第一种情况下,我有两个包含大量信息的数组($expl$lines),在第二种情况下,我试图使用生成器来避免将这些内存用于数组。

我是否以某种错误的方式使用了生成器的概念?如果没有,是否可以在不爆炸字符串的情况下实现它然后yield $expl[$key]

我尝试使用substr($string, $pos, strpos($string, PHP_EOL, $pos));,其中$pos 是字符串的位置,但我只能使用它调用一次getLines。

信息:

PHP 5.6

【问题讨论】:

  • 将这个“非常长的字符串”保存在内存中很可能会在适当的时候引起它自己的问题。我建议将shell_exec() 切换为proc_open(),然后将您的生成器放在yield fgets($pipes[1]); 上,然后在运行时直接从命令的标准输出中读取行。
  • 实际上,我无法编辑从 shell 返回输出的代码,因为它用于系统的许多其他部分,但无论如何感谢您的提示,也许我尝试创建一个独占功能为它。

标签: php string iterator generator explode


【解决方案1】:

从一段文本中提取行时如何使用生成器的示例。这有一个循环来逐行查找行,并使用yield 一次将每个段传回..

function getLines( $result )    {
    $start = 0;
    while (($end = strpos($result, PHP_EOL, $start)) !== false)   {
        $line = trim(substr($result, $start, $end - $start));
        yield $line;
        $start = $end+1;
    }
}

foreach ( getLines($test) as $line)  {
    echo ">".$line."<".PHP_EOL;
}

如您所见,函数调用的返回值用于驱动foreach,并将每一行输出到$line

在这段代码中$test是要解析的字符串。

【讨论】:

    猜你喜欢
    • 2023-04-06
    • 1970-01-01
    • 2013-10-18
    • 1970-01-01
    • 2019-07-15
    • 2022-01-02
    • 1970-01-01
    • 2012-11-06
    • 1970-01-01
    相关资源
    最近更新 更多