Wyodrębnić środkową sekcję wierszy pliku tekstowego?

17

Piszę skrypt PHP, który analizuje duży plik tekstowy i wykonuje z niego wstawki do bazy danych. Jednak na moim hoście plik jest za duży i osiągnąłem limit pamięci dla PHP.

Plik ma około 16 000 linii; Chcę podzielić go na cztery osobne pliki (na początku), aby sprawdzić, czy mogę je załadować.

Pierwsza część, z którą mogę się dostać head -4000 file.txt. Środkowe sekcje są nieco trudniejsze - myślałem o przekazaniu taildanych wyjściowych do head( tail -4001 file.txt | head -4000 > section2.txt), ale czy istnieje inny / lepszy sposób?

W rzeczywistości moja logika jest zawalona - w sekcji drugiej musiałbym zrobić coś takiego tail -12001 file.txt | head - 4000, a następnie obniżyć tailargument dla następnych sekcji. Już się mylę! : P

użytkownik394
źródło

Odpowiedzi:

27

Jeśli nie chcesz się zepsuć, ale nadal robisz to za pomocą taili head, istnieje przydatny sposób wywoływania tailprzy użyciu liczenia linii od początku, a nie do końca:

tail -n +4001 yourfile | head -4000

... Ale lepsze, automatyczne narzędzie przeznaczone tylko do dzielenia plików nazywa się ... split! Jest to także część jądra GNU, więc każdy normalny system Linux powinien to mieć. Oto jak możesz go użyć:

split -l 4000 yourInputFile thePrefixForOutputFiles

(Zobacz w man splitrazie wątpliwości.)

rozcietrzewiacz
źródło
19

Połączenie głowy i ogona, tak jak ty, zadziała, ale do tego skorzystam sed

sed -n '1,4000p' input_file # print lines 1-4000 of input_file

Pozwala to rozwiązać problem za pomocą funkcji szybkiej powłoki

chunk_it(){
    step=4
    start=1
    end=$step
    for n in {1..4} ; do
        sed -n "${start},${end}p" "$1" > "$1".$start-$end
        let start+=$step
        let end+=$step
    done
}

chunk_it your_file

Teraz masz swój_plik_4-4000 i twój_plik.4001-8000 i tak dalej.

Uwaga: wymaga bash

Sorpigal
źródło
3
Podoba mi się sed.
fanchyna
To nie działa dla mnie, ponieważ sed nie wychodzi. Wypisuje linie, które chcę ustawić na standardowe wyjście, ale muszę ctrl-c wydrukować, w wyniku czego nie mogę przekierować go do pliku. Wszelkie sugestie, aby uczynić go użytecznym?
Brent212
Domyśliłam się! „sed -n” <start_line>, <end_line> w <output_file> '<input_file> ”działa dla mnie.
Brent212
@ Brent212 Inną opcją, na którą należy zwrócić uwagę, jest to, że można również potokować go do mniejszej lub przekierować wyjście do pliku.
Kyle,