Mam formularz, który pozwala użytkownikowi przesłać plik tekstowy lub skopiować / wkleić zawartość pliku do obszaru tekstowego. Mogę łatwo je rozróżnić i umieścić dowolną z nich w zmiennej łańcuchowej, ale dokąd mam się udać?
Muszę iterować po każdej linii ciągu (najlepiej nie martwić się o nowe linie na różnych komputerach), upewnić się, że ma dokładnie jeden token (bez spacji, tabulatorów, przecinków itp.), Oczyścić dane, a następnie wygenerować zapytanie SQL na podstawie wszystkich linii.
Jestem dość dobrym programistą, więc znam ogólny pomysł, jak to zrobić, ale minęło tak dużo czasu, odkąd pracowałem z PHP, że czuję, że szukam niewłaściwych rzeczy iw ten sposób znajduję bezużyteczne informacje. Głównym problemem, który mam, jest to, że chcę czytać zawartość ciągu wiersz po wierszu. Gdyby to był plik, byłoby łatwo.
Poszukuję głównie przydatnych funkcji PHP, a nie algorytmu, jak to zrobić. Jakieś sugestie?
s($myString)->normalizeLineEndings()
jest dostępna na github.com/delight-im/PHP-Str (biblioteka na licencji MIT), która ma wiele innych przydatnych pomocników ciągów. Możesz rzucić okiem na kod źródłowy.Odpowiedzi:
preg_split
zmienna zawierająca tekst i iteruj po zwróconej tablicy:foreach(preg_split("/((\r?\n)|(\r\n?))/", $subject) as $line){ // do stuff with $line }
źródło
/((\r?\n)|(\r\n?))/
./((\r?\n)|(\n?\r))/
Chciałbym zaproponować znacznie szybszą (i wydajną pod względem pamięci) alternatywę:
strtok
zamiastpreg_split
.$separator = "\r\n"; $line = strtok($subject, $separator); while ($line !== false) { # do something with $line $line = strtok( $separator ); }
Testując wydajność, iterowałem 100 razy na pliku testowym z 17 tysiącami linii:
preg_split
zajęło to 27,7 sekundy, astrtok
zajęło 1,4 sekundy.Zauważ, że chociaż
$separator
jest zdefiniowane jako"\r\n"
,strtok
będzie się rozdzielać po każdym znaku - a od PHP 4.1.0, pomija puste linie / tokeny.Zobacz podręcznik strtok: http://php.net/strtok
źródło
prey_split
ani nieexplode
należy używać do tworzenia strukturalnych fragmentów ciągów. To tak, jakby celować w muchę z bazooką .strtok()
czegoś innego wewnątrz tejwhile
pętli zepsuje wszystko. Używałem go również do złapania wszystkiego w łańcuch do pierwszej spacji ( stackoverflow.com/a/2477411/1767412 ) i zajęło mi chwilę, aby zrozumieć, dlaczego sprawy nie idą zgodnie z planemJeśli potrzebujesz obsługiwać znaki nowej linii w różnych systemach, możesz po prostu użyć predefiniowanej stałej PHP PHP_EOL (http://php.net/manual/en/reserved.constants.php) i po prostu użyć funkcji eksploduj, aby uniknąć narzutu silnika wyrażeń regularnych .
źródło
PHP_EOL (string)
jest prawidłowy „End Of Line” symbol tej platformy.Jest to zbyt skomplikowane i brzydkie, ale moim zdaniem jest to droga:
$fp = fopen("php://memory", 'r+'); fputs($fp, $data); rewind($fp); while($line = fgets($fp)){ // deal with $line } fclose($fp);
źródło
php://temp
do przechowywania większych danych w tymczasowym pliku na dysku.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 }
^ tak poprawnie przerywasz linie , kompatybilne z
Regexp
różnymi platformami :)źródło
Potencjalne problemy z pamięcią
strtok
:Ponieważ jedno z sugerowanych rozwiązań wykorzystuje
strtok
, niestety nie wskazuje na potencjalny problem z pamięcią (choć twierdzi, że jest wydajna pod względem pamięci). Podczas korzystaniastrtok
według instrukcji , wyrażenie:Robi to poprzez załadowanie pliku do pamięci. Jeśli używasz dużych plików, musisz je opróżnić, jeśli skończysz przeglądać plik w pętli.
<?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('', ''); }
Jeśli interesują Cię tylko pliki fizyczne (np. Przetwarzanie danych):
Zgodnie z instrukcją do części upload plików można użyć
file
polecenia://Create the array $lines = file( $some_file ); foreach ( $lines as $line ) { //do something here. }
źródło
Odpowiedź Kyrila jest najlepsza, biorąc pod uwagę, że musisz umieć obsługiwać nowe linie na różnych maszynach.
Używam ich często:
źródło