Iterate em cada linha em uma string em PHP

Eu tenho um formulário que permite ao usuário carregar um arquivo de texto ou copiar / colar o conteúdo do arquivo em uma área de texto. Eu posso diferenciar facilmente entre os dois e colocar o que eles entraram em uma variável de string, mas onde eu vou de lá?

Eu preciso fazer uma iteração sobre cada linha da string (de preferência, não me preocupar com novas linhas em máquinas diferentes), certifique-se de que ele tenha exatamente um token (sem espaços, abas, vírgulas, etc.), desinfecte os dados e, em seguida, gere uma consulta SQL com base em todas as linhas.

Eu sou um programador bastante bom, então eu conheço a idéia geral sobre como fazê-lo, mas faz tanto tempo que trabalhei com o PHP e sinto que estou procurando as coisas erradas e, assim, encontrando informações inúteis. O problema principal que estou tendo é que eu quero ler o conteúdo da linha de caracteres por linha. Se fosse um arquivo, seria fácil.

Na maior parte, estou procurando por funções PHP úteis, e não como um algoritmo para como fazê-lo. Alguma sugestão?

preg_split a variável que contém o texto e iterar sobre a matriz retornada:

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

Gostaria de propor uma alternativa significativamente mais rápida (e eficiente em memory): strtok vez de preg_split .

 $separator = "\r\n"; $line = strtok($subject, $separator); while ($line !== false) { # do something with $line $line = strtok( $separator ); } 

Testando o desempenho, iteralizei 100 vezes em um arquivo de teste com 17 mil linhas: preg_split levou 27,7 segundos, enquanto o strtok demorou 1,4 segundos.

Observe que, embora o $separator seja definido como "\r\n" , o strtok será separado em qualquer caractere – e a partir do PHP4.1.0, salte as linhas / tokens vazias.

Veja a input manual do strtok: http://php.net/strtok

Se você precisa lidar com novas linhas em diferentes sistemas, você pode simplesmente usar a constante PHP predefinida PHP_EOL (http://php.net/manual/en/reserved.constants.php) e simplesmente usar explodir para evitar a sobrecarga do mecanismo de expressão regular .

 $lines = explode(PHP_EOL, $subject); 

É excessivamente complicado e feio, mas na minha opinião, esse é o caminho a seguir:

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

A resposta de Kyril é melhor, considerando que você precisa ser capaz de lidar com novas linhas em máquinas diferentes.

“Na maior parte, estou procurando por funções PHP úteis, e não como um algoritmo para como fazer isso. Alguma sugestão?”

Eu uso muito isso:

explode () pode ser usado para dividir uma string em uma matriz, dado um único delimitador.

implodir () é a contraparte da explosão, para passar da matriz de volta para a cadeia.

 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 } 

^ é assim que você quebra linhas corretamente , compatível com plataforma cruzada com Regexp 🙂

Problemas de memory potenciais com strtok :

Uma vez que uma das soluções sugeridas usa o strtok , infelizmente não indica um problema de memory potencial (embora ele seja eficiente em memory). Ao usar strtok acordo com o manual , o:

Observe que apenas a primeira chamada para strtok usa o argumento de string. Cada chamada subseqüente para strtok só precisa do token para usar, pois ele acompanha o local onde está na seqüência atual.

Isso faz isso carregando o arquivo na memory. Se você estiver usando arquivos grandes, você precisa liberá-los se você terminar de fazer o loop pelo arquivo.

  

Se você está apenas preocupado com arquivos físicos (por exemplo, datamining):

De acordo com o manual , para a parte do carregamento do arquivo você pode usar o comando do file :

  //Create the array $lines = file( $some_file ); foreach ( $lines as $line ) { //do something here. }