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

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

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

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

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

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

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

Я хотел бы предложить значительно более быструю (и эффективную по памяти) альтернативу: 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

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

 $lines = explode(PHP_EOL, $subject); 

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

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

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

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

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

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

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

 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 как вы правильно ломаете линии , кросс-платформенная совместимость с Regexp 🙂

Потенциальные проблемы с памятью с помощью 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. }