在PHP中迭代字符串中的每一行

时间:2009-09-22 21:27:48

标签: php string

我有一个表单,允许用户上传文本文件或将文件的内容复制/粘贴到textarea中。我可以很容易地区分这两者,并将他们输入的任何一个放入一个字符串变量,但我从哪里去?

我需要迭代字符串的每一行(最好不要担心不同机器上的换行符),确保它只有一个令牌(没有空格,制表符,逗号等),清理数据,然后生成基于所有行的SQL查询。

我是一个相当优秀的程序员,所以我知道如何做到的一般想法,但是我用PHP工作已经很久了,我觉得我在寻找错误的东西,从而得出无用的信息。我遇到的关键问题是我想逐行读取字符串的内容。如果它是一个文件,那将很容易。

我主要寻找有用的PHP函数,而不是如何做的算法。有什么建议吗?

7 个答案:

答案 0 :(得分:163)

preg_split包含文本的变量,并遍历返回的数组:

foreach(preg_split("/((\r?\n)|(\r\n?))/", $subject) as $line){
    // do stuff with $line
} 

答案 1 :(得分:135)

我想提出一个显着更快(和内存效率)替代方案:strtok而不是preg_split

$separator = "\r\n";
$line = strtok($subject, $separator);

while ($line !== false) {
    # do something with $line
    $line = strtok( $separator );
}

测试性能,我在17000行测试文件上迭代100次:preg_split花了27.7秒,而strtok花了1.4秒。

请注意,虽然$separator定义为"\r\n",但strtok将在任一字符上分开 - 从PHP4.1.0开始,跳过空行/标记。

请参阅strtok手册条目: http://php.net/strtok

答案 2 :(得分:93)

如果你需要处理不同系统中的换行,你可以简单地使用PHP预定义常量PHP_EOL(http://php.net/manual/en/reserved.constants.php)并简单地使用explode来避免开销。正则表达式引擎。

$lines = explode(PHP_EOL, $subject);

答案 3 :(得分:17)

过于复杂和丑陋,但在我看来,这是要走的路:

$fp = fopen("php://memory", 'r+');
fputs($fp, $data);
rewind($fp);
while($line = fgets($fp)){
  // deal with $line
}
fclose($fp);

答案 4 :(得分:4)

Kyril的答案是最好的,因为你需要能够在不同的机器上处理换行。

  

“我主要是寻找有用的PHP函数,而不是如何使用算法   去做吧。有什么建议吗?“

我经常使用这些:

    给定a,
  • explode()可用于将字符串拆分为数组 单一分隔符。
  • implode()是爆炸的对应物,从数组返回到字符串。

答案 5 :(得分:4)

foreach(preg_split('~[\r\n]+~', $text) as $line){
    if(empty($line) or ctype_space($line)) continue; // skip only spaces
    // if(!strlen($line = trim($line))) continue; // or trim by force and skip empty
    // $line is trimmed and nice here so use it
}

^ 这就是你正确打破行的方式,与Regexp跨平台兼容:)

答案 6 :(得分:3)

strtok的潜在内存问题:

由于其中一个建议的解决方案使用strtok,遗憾的是它没有指出潜在的内存问题(尽管它声称内存有效)。根据{{​​3}}使用strtok时:

  

请注意,只有第一次调用strtok才会使用字符串参数。   每次对strtok的后续调用只需要使用令牌,就像它一样   跟踪当前字符串中的位置。

通过将文件加载到内存中来实现此目的。如果您正在使用大文件,则需要在完成文件循环时刷新它们。

<?php
function process($str) {
    $line = strtok($str, PHP_EOL);

    /*do something with the first line here...*/

    while ($line !== FALSE) {
        // get the next line
        $line = strtok(PHP_EOL);

        /*do something with the rest of the lines here...*/

    }
    //the bit that frees up memory
    strtok('', '');
}

如果您只关注物理文件(例如,数据挖掘):

the manual,对于文件上传部分,您可以使用file命令:

 //Create the array
 $lines = file( $some_file );

 foreach ( $lines as $line ) {
   //do something here.
 }