Uzyskiwanie ostatniego dopasowania w pliku za pomocą grep

58

Jaki jest najlepszy sposób uzyskania tylko końcowego dopasowania wyrażenia regularnego w pliku przy użyciu grep?

Czy można rozpocząć grepowanie od końca pliku zamiast od początku i zatrzymać po znalezieniu pierwszego dopasowania?

Żołądź
źródło

Odpowiedzi:

85

Możesz spróbować

grep pattern file | tail -1

lub

tac file | grep pattern | head -1

lub

tac file | grep -m1 pattern
Cakemox
źródło
20
tac file | grep -m 1 pattern
Dennis Williamson,
1
Z dodanym ograniczeniem, że chciałem uzyskać numer wiersza ( grep -n) w rzeczywistym pliku, myślę, że tacprawie trzeba było unikać, chyba że chciałem zrobić odejmowanie wc -l. W przeciwnym razie tacz grep -m1ma sens.
Nick Merrill
1
Chciałbym zobaczyć bardziej wydajną wersję niż ta, ponieważ próbuję wyszukać plik 20 GB.
Jeff
Odpowiedź @DennisWilliamson jest znacznie lepsza, ponieważ grepprzestanie działać po pierwszym meczu. bez -m 1, grepnajpierw znajdzie wszystkie pasujące wzorce w pliku , a następnie headpokaże tylko pierwsze - znacznie mniej wydajne. Dennis, zastanów się nad opublikowaniem tego w osobnej odpowiedzi!
gilad mayani
1

Dla kogoś pracującego z dużymi plikami tekstowymi w systemach Unix / Linux / Mac / Cygwin. Jeśli używasz systemu Windows, sprawdź to na temat narzędzi systemu Linux w systemie Windows: https://stackoverflow.com/questions/3519738/what-is-the-best-way-to-use-linux-utilities-under-windows .

Można wykonać ten przepływ pracy, aby uzyskać dobrą wydajność:

  1. kompresuj za pomocą gzip
  2. użyj zindex (na github: https://github.com/mattgodbolt/zindex ), aby zindeksować plik odpowiednim kluczem
  3. odpytuj indeksowany plik z zqpakietu.

Cytat z jego pliku github:

Tworzenie indeksu

zindex musi zostać poinformowany, która część każdej linii stanowi indeks. Można tego dokonać za pomocą wyrażenia regularnego, pola lub poprzez potokowanie każdej linii przez zewnętrzny program.

Domyślnie zindex tworzy indeks file.gz.zindex, gdy zostanie poproszony o indeksowanie file.gz.

Przykład:

utwórz indeks w wierszach pasujących do liczbowego wyrażenia regularnego. Grupa przechwytywania wskazuje część, która ma być indeksowana, a opcje pokazują, że każda linia ma unikalny indeks numeryczny.

$ zindex file.gz --regex 'id:([0-9]+)' --numeric --unique

Przykład: utwórz indeks w drugim polu pliku CSV:

$ zindex file.gz --delimiter , --field 2 

Przykład:

utwórz indeks w polu JSON orderId.id w dowolnym elemencie tablicy działań katalogu głównego dokumentu (wymaga jq). Kwerenda jq tworzy tablicę wszystkich orderId.ids, a następnie łączy je spacją, aby zapewnić, że każda pojedyncza linia potokowana do jq tworzy pojedynczy wiersz danych wyjściowych, z wieloma dopasowaniami oddzielonymi spacjami (który jest domyślnym separatorem).

$ zindex file.gz --pipe "jq --raw-output --unbuffered '[.actions[].orderId.id] | join(\" \")'" 

Zapytanie o indeks

Program ZQ służy do tworzenia zapytań o indeks. Podano nazwę skompresowanego pliku i listę zapytań. Na przykład:

$ zq file.gz 1023 4443 554 

Możliwe jest również wyjście według numeru wiersza, więc aby wydrukować wiersze 1 i 1000 z pliku:

$ zq file.gz --line 1 1000
biocyberman
źródło
1

Zawsze używam cat (ale to sprawia, że ​​trochę dłużej): cat file | grep pattern | tail -1

Zrzuciłbym winę na nauczyciela linux na kursie na studiach, który uwielbia koty :))))

- Nie musisz najpierw przechwycić pliku, zanim go grepujesz. grep pattern file | tail -1i jest również bardziej wydajny.

Ismail Guneydas
źródło
6
To tylko pierwsza część odpowiedzi Cakemoxa, z wyjątkiem gorszych.
sierpień
Działa, ale robi niepotrzebne kroki. W przypadku lekkiego użytkowania to rozwiązanie działa dobrze, ale nie działa dobrze. Powodem jest to, że nie potrzebujesz catpliku i potokować go grep. Możesz grepprzeszukać plik bezpośrednio przez grep pattern file(a następnie użyć, tailaby zwrócić ostatni wynik), jak w odpowiedzi Cakemox.
jvriesem