Jeśli ta „duża” oznacza około 10 milionów linii lub więcej, lepiej użyć tail. Nie jest w stanie edytować w miejscu, ale jego wydajność sprawia, że brakowi można wybaczyć:
tail -n +2 large_file > large_file.new
Edytuj, aby pokazać różnice czasowe:
( awkkod dodany przez Jaypal, aby mieć czasy wykonania na tym samym komputerze (procesor 2,2 GHz).)
bash-4.2$ seq 1000000 > bigfile.txt # further file creations skipped
bash-4.2$ time sed -i 1d bigfile.txt
time 0m4.318s
bash-4.2$ time ed -s <<< $'1d\nwq' bigfile.txt
time 0m0.533s
bash-4.2$ time perl -pi -e 'undef$_ if$.==1' bigfile.txt
time 0m0.626s
bash-4.2$ time { tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt; }
time 0m0.034s
bash-4.2$ time { awk 'NR>1 {print}' bigfile.txt > newfile.txt && mv -f newfile.txt bigfile.txt; }
time 0m0.328s
To jest naprawdę fajne! Zrobiłem to samo z awki otrzymałem następujący wynik[jaypal:~/Temp] seq 1000000 > bigfile.txt [jaypal:~/Temp] time awk 'NR>1 {print}' bigfile.txt >newfile.txt real 0m0.649s user 0m0.601s sys 0m0.033s
jaypal singh
1
@Jaypal, dodałem Twój kod do listy alternatyw. Na mojej maszynie było jeszcze szybciej. Dziwne, spodziewałem się awk, że występ będzie bliższy sed. (Uwaga dla siebie: nigdy nie oczekuj - przetestuj zamiast tego)
manatwork
To było najlepsze rozwiązanie w moim przypadku: tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt;używam jednego pliku z blokadą do śledzenia pojedynczej listy zadań wykorzystywanej przez wiele procesów. Zacząłem co początkowy plakat wykorzystane: sed -i 1d large_file . Powodowało to blokowanie pliku na 1-2 sekundy. tail/mvKombi kończy niemal natychmiast. Dziękuję Ci!
Chris Adams
6
Nie ma sposobu, aby skutecznie usunąć rzeczy z początku pliku. Usuwanie danych od początku wymaga ponownego zapisania całego pliku.
Obcinanie od końca pliku może być jednak bardzo szybkie (system operacyjny musi tylko dostosować informacje o rozmiarze pliku, ewentualnie usuwając nieużywane teraz bloki). Zasadniczo nie jest to możliwe, gdy próbujesz usunąć z nagłówka pliku.
Teoretycznie może być „szybki”, jeśli dokładnie usuniesz cały blok / zakres, ale nie ma do tego żadnych wywołań systemowych, więc będziesz musiał polegać na specyficznej dla systemu plików semantyce (jeśli taka istnieje). (Albo mam jakąś formę przesunięcia w pierwszym bloku / zasięgu, aby zaznaczyć prawdziwy początek pliku, chyba. Nigdy o tym nie słyszałem.)
Jeśli plik jest bardzo duży, narzut We / Wy prawdopodobnie będzie (prawdopodobnie znacznie) większy niż narzut CPU wymagany do przetworzenia końca linii.
Mat.
Masz rację. Jednak może istnieć różnica w sposobie, w jaki narzędzia uzyskują dostęp do zawartości pliku. Najlepiej jest nie przetwarzać linii po linii, gdy nie jest to konieczne, lub przynajmniej nie czytać linii po linii, gdy nie jest to konieczne.
manatwork
2
Dziwię się, że różnica jest tak duża w twoich wynikach i mogę odtworzyć ją z tym rozmiarem pliku tutaj. Korzyści wydają się maleć wraz ze wzrostem wielkości pliku (wypróbowane z sekw. 10M, 15s dla sed, 5s dla ed). W każdym razie dobre wskazówki (+1).
Mat.
Począwszy od wersji 3.15, Linux ma teraz interfejs API do zwijania części pliku w systemach plików opartych na pewnym zakresie, ale przynajmniej dla ext4, które można wykonać tylko na pełnych blokach (zwykle 4k).
Stéphane Chazelas
Nawet jeśli edycja wymaga przepisania całego pliku, czasami bardzo przydatne jest posiadanie narzędzi wiersza poleceń do wydajnej edycji. W moim przypadku pomogło to, gdy musiałem usunąć pierwszy wiersz pliku, który był większy niż moja całkowita pamięć RAM systemu.
Jason
3
Najbardziej wydajna metoda, nie rób tego! Jeśli tak, to w każdym razie potrzebujesz dwa razy więcej „dużego” miejsca na dysku i marnujesz operacje wejścia / wyjścia.
Jeśli utknąłeś z dużym plikiem, który chcesz odczytać bez pierwszej linii, poczekaj, aż będziesz musiał go przeczytać w celu usunięcia pierwszej linii. Jeśli chcesz wysłać plik ze standardowego programu do programu, użyj tail, aby to zrobić:
tail -n +2 | your_program
Gdy potrzebujesz odczytać plik, możesz skorzystać z okazji, aby usunąć pierwszą linię, ale tylko jeśli masz potrzebne miejsce na dysku:
tail -n +2 | tee large_file2 | your_program
Jeśli nie możesz czytać ze standardowego wejścia, użyj fifo:
Niestandardowy system plików (zaimplementowany za pomocą FUSE lub podobnego mechanizmu) może ujawnić katalog, którego zawartość jest dokładnie taka sama, jak już istniejący katalog gdzie indziej, ale z plikami obciętymi, jak chcesz. System plików przetłumaczy wszystkie przesunięcia plików. W takim przypadku nie trzeba wykonywać czasochłonnego przepisywania pliku.
Ale biorąc pod uwagę, że ten pomysł jest bardzo trywialny, chyba że masz dziesiątki terabajtów takich plików, wdrożenie takiego systemu plików byłoby zbyt drogie / czasochłonne, aby było praktyczne.
tail
wolę liczyć czas zarówno na usunięcie pierwszego wiersza, jak i zastąpieniebigfile.txt
gobigfile.new
.awk
i otrzymałem następujący wynik[jaypal:~/Temp] seq 1000000 > bigfile.txt [jaypal:~/Temp] time awk 'NR>1 {print}' bigfile.txt >newfile.txt real 0m0.649s user 0m0.601s sys 0m0.033s
awk
, że występ będzie bliższysed
. (Uwaga dla siebie: nigdy nie oczekuj - przetestuj zamiast tego)tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt;
używam jednego pliku z blokadą do śledzenia pojedynczej listy zadań wykorzystywanej przez wiele procesów. Zacząłem co początkowy plakat wykorzystane:sed -i 1d large_file
. Powodowało to blokowanie pliku na 1-2 sekundy.tail/mv
Kombi kończy niemal natychmiast. Dziękuję Ci!Nie ma sposobu, aby skutecznie usunąć rzeczy z początku pliku. Usuwanie danych od początku wymaga ponownego zapisania całego pliku.
Obcinanie od końca pliku może być jednak bardzo szybkie (system operacyjny musi tylko dostosować informacje o rozmiarze pliku, ewentualnie usuwając nieużywane teraz bloki). Zasadniczo nie jest to możliwe, gdy próbujesz usunąć z nagłówka pliku.
Teoretycznie może być „szybki”, jeśli dokładnie usuniesz cały blok / zakres, ale nie ma do tego żadnych wywołań systemowych, więc będziesz musiał polegać na specyficznej dla systemu plików semantyce (jeśli taka istnieje). (Albo mam jakąś formę przesunięcia w pierwszym bloku / zasięgu, aby zaznaczyć prawdziwy początek pliku, chyba. Nigdy o tym nie słyszałem.)
źródło
Najbardziej wydajna metoda, nie rób tego! Jeśli tak, to w każdym razie potrzebujesz dwa razy więcej „dużego” miejsca na dysku i marnujesz operacje wejścia / wyjścia.
Jeśli utknąłeś z dużym plikiem, który chcesz odczytać bez pierwszej linii, poczekaj, aż będziesz musiał go przeczytać w celu usunięcia pierwszej linii. Jeśli chcesz wysłać plik ze standardowego programu do programu, użyj tail, aby to zrobić:
Gdy potrzebujesz odczytać plik, możesz skorzystać z okazji, aby usunąć pierwszą linię, ale tylko jeśli masz potrzebne miejsce na dysku:
Jeśli nie możesz czytać ze standardowego wejścia, użyj fifo:
jeszcze lepiej, jeśli używasz bash, skorzystaj z substytucji procesu:
Jeśli potrzebujesz szukać w pliku, nie widzę lepszego rozwiązania niż nie utknięcie w pliku. Jeśli ten plik został wygenerowany przez stdout:
W przeciwnym razie zawsze istnieje rozwiązanie FIFO lub proces zastępowania procesów:
źródło
Możesz używać Vima w trybie Ex:
1
wybierz pierwszą linięd
kasowaćx
Zapisz i zamknijźródło
To tylko teoria, ale ...
Niestandardowy system plików (zaimplementowany za pomocą FUSE lub podobnego mechanizmu) może ujawnić katalog, którego zawartość jest dokładnie taka sama, jak już istniejący katalog gdzie indziej, ale z plikami obciętymi, jak chcesz. System plików przetłumaczy wszystkie przesunięcia plików. W takim przypadku nie trzeba wykonywać czasochłonnego przepisywania pliku.
Ale biorąc pod uwagę, że ten pomysł jest bardzo trywialny, chyba że masz dziesiątki terabajtów takich plików, wdrożenie takiego systemu plików byłoby zbyt drogie / czasochłonne, aby było praktyczne.
źródło