Перебирать каждую строку в строке в PHP - PullRequest
111 голосов
/ 23 сентября 2009

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

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

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

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

Ответы [ 7 ]

163 голосов
/ 23 сентября 2009

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

foreach(preg_split("/((\r?\n)|(\r\n?))/", $subject) as $line){
    // do stuff with $line
} 
135 голосов
/ 09 февраля 2013

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

93 голосов
/ 25 декабря 2012

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

$lines = explode(PHP_EOL, $subject);
18 голосов
/ 12 июля 2013

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

$fp = fopen("php://memory", 'r+');
fputs($fp, $data);
rewind($fp);
while($line = fgets($fp)){
  // deal with $line
}
fclose($fp);
4 голосов
/ 20 июля 2013
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:)

4 голосов
/ 23 сентября 2009

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

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

Я часто их использую:

  • explode () может использоваться для разбиения строки на массив, учитывая одиночный разделитель.
  • implode () является аналогом explode для перехода из массива обратно в строку.
3 голосов
/ 30 августа 2017

Потенциальные проблемы с памятью при 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('', '');
}

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

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

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

 foreach ( $lines as $line ) {
   //do something here.
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...