Mam plik z około 30 000 000 wierszy (Radius Accounting) i muszę znaleźć ostatnie dopasowanie dla danego wzorca.
Komenda:
tac accounting.log | grep $pattern
daje to, czego potrzebuję, ale jest zbyt wolne, ponieważ system operacyjny musi najpierw odczytać cały plik, a następnie wysłać go do potoku.
Potrzebuję więc czegoś szybkiego, co umożliwi odczytanie pliku od ostatniej linii do pierwszej.
źródło
tac
, chodziło mi o to, że to nie pomaga, chyba że używasz również,-m
ponieważ plik musi być w całości odczytany przez dwa programy. W przeciwnym razie możesz po prostu wyszukać wszystkie wystąpienia i zachować tylko ostatnie, tak jak jatail -n 1
.grep -m
powinien być dość wydajny.grep -m
nim jest. OP nie korzystał,-m
więc zarówno grep, jak i tac przetwarzały całość.awk
linii?Powód dlaczego
nie kończy się przy pierwszym meczu z powodu buforowania.
Zwykle
head -n 1
kończy się po przeczytaniu linii. Więcgrep
powinien dostać SIGPIPE i wyjść tak szybko, jak tylko napisze drugą linię.Ale dzieje się tak, ponieważ ponieważ jego wyjście nie trafia do terminala,
grep
buforuje je. Oznacza to, że nie pisze tego, dopóki nie zgromadzi wystarczającej ilości (4096 bajtów w moim teście z GNU grep).Oznacza to, że
grep
nie wyjdzie przed zapisaniem 8192 bajtów danych, więc prawdopodobnie sporo wierszy.Dzięki GNU
grep
możesz sprawić, że wyjdzie wcześniej, używając polecenia,--line-buffered
które wypisuje wiersze, gdy tylko zostaną znalezione, niezależnie od tego, czy przejdzie do terminala, czy nie. Opuszczałbygrep
wtedy drugą znalezioną linię.Ale z GNU i
grep
tak możesz użyć-m 1
zamiast tego, jak pokazał @terdon, co jest lepsze, gdy wychodzi z pierwszego meczu.Jeśli
grep
niegrep
jesteś GNU , możesz użyćsed
lubawk
zamiast tego. Aletac
będąc poleceniem GNU, wątpię, abyś znalazł system, wtac
którymgrep
nie ma GNUgrep
.Niektóre systemy muszą
tail -r
robić to samo co GNUtac
.Zauważ, że w przypadku zwykłych (możliwych do przeglądania) plików
tac
itail -r
są one wydajne, ponieważ odczytują pliki do tyłu, nie tylko czytają plik w całości przed wydrukowaniem go do tyłu (tak jak w przypadku sed @ slm lubtac
w przypadku plików nieregularnych) .W systemach, w których ani
tac
nietail -r
są dostępne, jedynymi opcjami są ręczne odczytywanie wstecz przy użyciu języków programowania takich jakperl
lub użycie:Lub:
Ale oznacza to znalezienie wszystkich dopasowań i wydrukowanie tylko ostatniego.
źródło
Oto możliwe rozwiązanie, które znajdzie lokalizację pierwszego wystąpienia wzorca z ostatniego:
Wykorzystuje to następujące przełączniki
-s
i :-r
tac
źródło
Korzystanie z sed
Pokazywanie alternatywnych metod dla dokładnej odpowiedzi @ Terdona za pomocą
sed
:Przykłady
Korzystanie z Perla
Jako bonus, oto nieco łatwiejszy do zapamiętania zapis w Perlu:
Przykład
źródło
sed
) będzie prawdopodobnie kilka rzędów wielkości wolniejsze niżgrep 5 | tail -n1
lubsed '/5/h;$!d;g'
. Potencjalnie zużyje również dużo pamięci. Nie jest dużo bardziej przenośny, ponieważ nadal używasz GNUgrep -m
.