W tej odpowiedzi ( Jak mogę usunąć pierwszy wiersz pliku za pomocą sed? ) Istnieją dwa sposoby usunięcia pierwszego rekordu w pliku:
sed '1d' $file >> headerless.txt
** ---------------- LUB ---------------- **
tail -n +2 $file >> headerless.txt
Osobiście uważam, że ta tail
opcja jest kosmetycznie przyjemniejsza i bardziej czytelna, ale prawdopodobnie dlatego, że mam wyzwanie.
Która metoda jest najszybsza?
sed
jest bardziej przenośna: „+2” dlatail
działa dobrze na Ubuntu, który używa GNUtail
, ale nie działa na BSDtail
.tail
brakiem zgodności między platformami.-n
opcji i korzystał ze składnitail +2 $file
. Zobacz freebsd.org/cgi/… Możliwe, że myślałeś o tym, a nie o jednym ze współczesnych BSD.Odpowiedzi:
Wydajność
sed
vs.,tail
aby usunąć pierwszą linię plikuTL; DR
sed
jest bardzo wydajny i wszechstronny, ale to powoduje, że działa wolno, szczególnie w przypadku dużych plików z wieloma liniami.tail
robi tylko jedną prostą rzecz, ale ta robi dobrze i szybko, nawet dla większych plików z wieloma liniami.Dla małych i średnich plików
sed
itail
działają podobnie szybko (lub wolno, w zależności od oczekiwań). Jednak w przypadku większych plików wejściowych (wiele MB) różnica wydajności znacznie rośnie (rząd wielkości dla plików w zakresie setek MB), przytail
wyraźnie lepszych wynikachsed
.Eksperyment
Ogólne przygotowania:
Nasze polecenia do analizy to:
Zauważ, że przesyłam dane wyjściowe za
/dev/null
każdym razem, aby wyeliminować dane wyjściowe terminala lub zapisy plików jako wąskie gardło wydajności.Skonfigurujmy dysk RAM, aby wyeliminować We / Wy dysku jako potencjalne wąskie gardło. Ja osobiście mam
tmpfs
zamontowany w,/tmp
więc po prostu umieściłem gotestfile
w tym eksperymencie.Następnie raz tworzę losowy plik testowy zawierający określoną liczbę linii
$numoflines
o losowej długości linii i losowych danych za pomocą tego polecenia (zauważ, że zdecydowanie nie jest optymalny, staje się naprawdę wolny dla około> 2M linii, ale kogo to obchodzi, to nie jest rzecz, którą analizujemy):Och, przy okazji. mój testowy laptop działa pod kontrolą Ubuntu 16.04, 64-bit na procesorze Intel i5-6200U. Dla porównania.
Czas dużych plików:
Konfigurowanie ogromnej
testfile
:Uruchomienie powyższej komendy z
numoflines=10000000
wygenerowanym losowym plikiem zawierającym 10 mln linii, zajmującym nieco ponad 600 MB - jest dość duże, ale zacznijmy od niego, ponieważ możemy:Wykonaj bieg na czas z naszym ogromnym
testfile
:Teraz zróbmy tylko jeden czas z obu komend, aby oszacować, z jaką wielkością pracujemy.
Widzimy już naprawdę wyraźny wynik dla dużych plików,
tail
jest o wiele szybszy niżsed
. Ale dla zabawy i dla pewności, że nie ma przypadkowych efektów ubocznych, które mogą mieć duże znaczenie, zróbmy to 100 razy:Wniosek pozostaje ten sam,
sed
jest nieefektywny, aby usunąć pierwszą linię dużego pliku,tail
należy tam użyć.I tak, wiem, że konstrukcje pętli Basha są powolne, ale robimy tutaj tylko kilka iteracji, a czas potrzebny na zwykłą pętlę nie jest znaczący w porównaniu z
sed
/tail
runtimes.Czas małe pliki:
Konfigurowanie małego
testfile
:Teraz dla kompletności, spójrzmy na bardziej powszechny przypadek, w którym masz mały plik wejściowy w zakresie kB. Utwórzmy losowy plik wejściowy
numoflines=100
, wyglądający tak:Wykonaj bieg na czas za pomocą naszego małego
testfile
:Ponieważ możemy oczekiwać, że czasy tak małych plików mieszczą się w zakresie kilku milisekund od doświadczenia, zróbmy od razu 1000 iteracji:
Jak widać, czasy są dość podobne, nie ma wiele do interpretacji ani zastanowienia. W przypadku małych plików oba narzędzia są równie dobrze dostosowane.
źródło
awk
może to zrobić. Moje oryginalne pytanie opierało się na linku, który znalazłem w pierwszej kolejności. Po całej ciężkiej pracy proszę doradzić, czy powinienem usunąć sięawk
jako kandydat na rozwiązanie i skupić się na pierwotnym zakresie projektu tylkosed
itail
.awk 'NR > 1'
, co ciekawe).Oto kolejna alternatywa, wykorzystująca tylko wbudowane bash i
cat
:$file
zostaje przekierowany do{ }
grupy poleceń. Poread
prostu czyta i odrzuca pierwszą linię. Reszta strumienia jest następnie przesyłana potokowo, docat
której zapisuje go do pliku docelowego.Na moim Ubuntu 16.04 wydajność tego i
tail
rozwiązania jest bardzo podobna. Utworzyłem obszerny plik testowy zseq
:tail
rozwiązanie:cat
/ rozwiązanie klamrowe:Mam jednak teraz tylko pod ręką maszynę Wirtualną Ubuntu i widziałem znaczne różnice w czasie obu tych programów, choć wszystkie są na tym samym boisku.
źródło
tail
ale nadal uważam, żeread
opcja jest bardzo fajna.Próbując w moim systemie i poprzedzając każdą komendę
time
, otrzymałem następujące wyniki:sed:
i ogon:
co sugeruje, że w moim systemie przynajmniej AMD FX 8250 z systemem Ubuntu 16.04, tail jest znacznie szybszy. Plik testowy miał 10 000 linii o rozmiarze 540k. Plik został odczytany z dysku twardego.
źródło
sed
może odgrywać rolę w tym wyniku, w takiej kolejności, w jakiej zostałeś przetestowany.sed
było około dwa razy szybsze.Nie ma obiektywnego sposobu, aby powiedzieć, co jest lepsze, ponieważ
sed
itail
nie są jedynymi rzeczami, które działają w systemie podczas wykonywania programu. Wiele czynników, takich jak dyskowe operacje we / wy, sieciowe operacje we / wy, przerwania procesora dla procesów o wyższym priorytecie - wszystkie te czynniki wpływają na szybkość działania programu.Oba są napisane w C, więc nie jest to kwestia językowa, ale bardziej środowiskowa. Na przykład mam dysk SSD i w moim systemie zajmie to trochę czasu w mikrosekundach, ale w przypadku tego samego pliku na dysku twardym zajmie to więcej czasu, ponieważ dyski twarde są znacznie wolniejsze. Sprzęt również odgrywa w tym rolę.
Podczas rozważania wyboru polecenia należy pamiętać o kilku rzeczach:
sed
to edytor strumieniowy do przekształcania tekstu.tail
służy do wyprowadzania określonych wierszy tekstu. Jeśli chcesz poradzić sobie z liniami i tylko je wydrukować, użyjtail
. Jeśli chcesz edytować tekst, użyjsed
.tail
ma znacznie prostszą składnię niżsed
, więc używaj tego, co możesz przeczytać sam i tego, co inni mogą przeczytać.Innym ważnym czynnikiem jest ilość przetwarzanych danych. Małe pliki nie dają żadnej różnicy w wydajności. Obraz staje się interesujący, gdy masz do czynienia z dużymi plikami. Dzięki plikowi BIGFILE.txt o pojemności 2 GB możemy zauważyć, że
sed
ma o wiele więcej wywołań systemowychtail
i działa znacznie wolniej.źródło
tail
lepiej niżsed
- użyj tego. Osobiście skorzystałbym,python
aawk
raczejsed
dlatego, że może się skomplikować. Poza tym, jeśli martwisz się wydajnością, spójrzmy prawdzie w oczy - tutaj widzisz wyniki w mikrosekundach. Nie poczujesz różnicy, chyba że jest to cholernie ogromny plik w zasięgu gigabajtów, który próbujesz przeczytaćawk
odpowiedź:) ... Moje pytanie było oparte na innym pytaniu i odpowiedziach AU (w linku) i tam nigdy nie wspomnianoawk
. Zgadzam się, że różnica czasu jest nominalna dla małych plików. Próbowałem tylko rozwinąć dobre nawyki.awk 'NR!=1' input_file.txt
. Daje mi ten sam wynik, około 150 milisekund, tę samą liczbę dla obutail
ised
. Ale z drugiej strony, używam SSD, więc powiedziałbym, że liczy się dysk twardy i procesor, a nie polecenie.sed
zajmuje znacznie ponad 3 minuty, podczas gdytail
potrzebuje tylko około 20 sekund. To naprawdę nie jest tak duże, ale zdecydowanie nie w zakresie GB.Najlepsza odpowiedź nie uwzględniała działania dysku
> /dev/null
jeśli masz duży plik i nie chcesz tworzyć tymczasowego duplikatu na dysku, spróbuj
vim -c
Edycja: jeśli plik jest większy niż dostępna pamięć
vim -c
nie działa, wygląda na to, że nie jest wystarczająco inteligentny, aby wykonać przyrostowe ładowanie plikuźródło
Inne odpowiedzi pokazują dobrze, co jest lepsze, aby utworzyć nowy plik bez pierwszej linii. Jeśli chcesz edytować plik w przeciwieństwie do tworzenia nowego pliku, założę się,
ed
że byłby szybszy, ponieważ w ogóle nie powinien tworzyć nowego pliku. Ale musisz poszukać, jak usunąć linię,ed
ponieważ użyłem jej tylko raz.źródło