Итерации по каждой строке в строке в PHP

У меня есть форма, которая позволяет пользователю либо загружать текстовый файл, либо копировать/вставлять содержимое файла в текстовое поле. Я могу легко разграничить их между двумя, и указать, какой из них они ввели в строковую переменную, но куда мне идти?

Мне нужно перебирать каждую строку строки (желательно не беспокоиться о новых строках на разных машинах), убедитесь, что она имеет ровно один токен (без пробелов, вкладок, запятых и т.д.), дезинфицирует данные, затем генерирует SQL-запрос, основанный на всех строках.

Я довольно хороший программист, поэтому я знаю общую идею о том, как это сделать, но так давно я работал с PHP, что, по-моему, я искал неправильные вещи и, следовательно, придумывал бесполезную информацию, Основная проблема, с которой я сталкиваюсь, заключается в том, что я хочу прочитать содержимое строки по строкам. Если бы это был файл, это было бы легко.

В основном я ищу полезные функции PHP, а не алгоритм, как это сделать. Любые предложения?

Ответ 1

preg_split переменная, содержащая текст, и итерация по возвращенному массиву:

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

Ответ 2

Я хотел бы предложить значительно более быструю (и эффективную с точки зрения памяти) альтернативу: strtok а не preg_split.

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

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

Тестирование производительности, я повторил 100 раз над тестовым файлом с 17 тысячами строк: preg_split заняло 27,7 секунды, тогда как strtok заняло 1,4 секунды.

Обратите внимание, что хотя $separator определяется как "\r\n", strtok будет разделяться на любом символе - и с PHP4.1.0 пропустить пустые строки/токены.

См. руководство пользователя strtok: http://php.net/strtok

Ответ 3

Если вам нужно обрабатывать новые строки в разных системах, вы можете просто использовать PHP предопределенную константу PHP_EOL (http://php.net/manual/en/reserved.constants.php) и просто использовать explode, чтобы избежать накладных расходов двигатель регулярного выражения.

$lines = explode(PHP_EOL, $subject);

Ответ 4

Это слишком сложно и уродливо, но, на мой взгляд, это путь:

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

Ответ 5

Ответ Кирилла лучше всего учитывать, что вы должны иметь возможность обрабатывать новые строки на разных машинах.

"Я в основном ищу полезные функции PHP, а не алгоритм, как это сделать. Любые предложения?"

Я использую их много:

explode() можно использовать для разбиения строки на массив с учетом одного разделителя.

implode() - это разбить аналогию, чтобы перейти от массива к строке.

Ответ 6

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:)

Ответ 7

Потенциальные проблемы с памятью с помощью strtok:

Так как в одном из предложенных решений используется strtok, к сожалению, он не указывает на потенциальную проблему с памятью (хотя он утверждает, что он эффективен с точки зрения памяти). При использовании 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('', '');
}

Если вы занимаетесь только физическими файлами (например, datamining):

В соответствии с руководством для части загрузки файла вы можете использовать команду file:

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

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