Jestem pewien, że ktoś miał poniższą potrzebę, jaki jest szybki sposób dzielenia ogromnego pliku .gz po linii? Podstawowy plik tekstowy ma 120 milionów wierszy. Nie mam wystarczającej ilości miejsca na dysku, aby rozpalić cały plik naraz, więc zastanawiałem się, czy ktoś wie o skrypcie bash / perl lub narzędziu, które mogłoby podzielić plik (.gz lub wewnętrzny .txt) na pliki linii 3x 40mn . tzn. nazywając to tak:
bash splitter.sh hugefile.txt.gz 4000000 1
would get lines 1 to 40 mn
bash splitter.sh hugefile.txt.gz 4000000 2
would get lines 40mn to 80 mn
bash splitter.sh hugefile.txt.gz 4000000 3
would get lines 80mn to 120 mn
Być może robi serię tych rozwiązań, czy też gunzip -c wymagałby wystarczającej ilości miejsca, aby rozpakować cały plik (tj. Oryginalny problem): gunzip -c hugefile.txt.gz | głowica 4000000
Uwaga: nie mogę dostać dodatkowego dysku.
Dzięki!
Odpowiedzi:
Jak to zrobić najlepiej, zależy od tego, czego chcesz:
Jeśli chcesz pojedynczą część pliku , twój pomysł użyć
gunzip
ihead
ma rację. Możesz użyć:Spowodowałoby to wyświetlenie pierwszych 4000000 wierszy przy standardowym wyjściu - prawdopodobnie chcesz dołączyć kolejny potok, aby faktycznie zrobić coś z danymi.
Aby uzyskać inne części, użyj kombinacji
head
itail
, na przykład:dostać drugi blok.
Nie,
gunzip -c
nie wymaga miejsca na dysku - robi wszystko w pamięci, a następnie przesyła strumieniowo na standardowe wyjście.Jeśli chcesz utworzyć wszystkie części za jednym razem , wydajniej jest utworzyć je wszystkie za pomocą jednego polecenia, ponieważ wtedy plik wejściowy jest odczytywany tylko raz. Jednym dobrym rozwiązaniem jest użycie
split
; szczegóły znajdziesz w odpowiedzi jima mcnamary.źródło
gzip
nie wie o limicie (który pochodzi z innego procesu). Jeślihead
zostanie użyty,head
zakończy działanie, gdy otrzyma wystarczającą ilość, i nastąpi jego propagacjagzip
(za pośrednictwem SIGPIPE, patrz Wikipedia). Dotail
tego nie jest możliwe, więc tak,gzip
będzie rozpakować wszystko.do dzielenia potoku użyj polecenia gunzip -c lub zcat, aby otworzyć plik
Dodaj specyfikacje wyjściowe do polecenia split.
źródło
Podczas pracy nad (nieodwracalnym) strumieniem, będziesz chciał użyć formy „+ N” ogona, aby uzyskać linie zaczynające się od linii N.
źródło
Rozważałbym użycie podziału .
źródło
Bezpośrednio podziel plik .gz na pliki .gz:
Myślę, że tego właśnie chciał OP, ponieważ nie ma dużo miejsca.
źródło
Oto skrypt Pythona do otwierania globalnego zestawu plików z katalogu, pistoletowania ich w razie potrzeby i odczytywania ich wiersz po wierszu. Wykorzystuje tylko przestrzeń potrzebną w pamięci do przechowywania nazw plików i bieżącej linii, a także niewielki narzut.
Polecenie print line wyśle każdą linię do standardowego wyjścia, abyś mógł przekierować do pliku. Ewentualnie, jeśli dasz nam znać, co chcesz zrobić z liniami, mogę dodać to do skryptu Pythona i nie będziesz musiał zostawiać fragmentów pliku leżących wokół.
źródło
Oto program perlowy, którego można użyć do odczytu standardowego wejścia i podziału linii, przesyłając każdą grupę do osobnego polecenia, które może użyć zmiennej powłoki $ SPLIT, aby skierować ją do innego miejsca docelowego. W twoim przypadku zostanie wywołane za pomocą
zcat hugefile.txt.gz | perl xsplit.pl 40000000 'cat > tmp$SPLIT.txt; do_something tmp$SPLIT.txt; rm tmp$SPLIT.txt'
Niestety przetwarzanie w wierszu polecenia jest trochę nieprzyzwoite, ale masz pomysł.
źródło