Зворотне стискання


44

Скажімо, у мене дійсно великий текстовий файл (близько 10 000 000 рядків). Мені потрібно grepце з кінця і зберегти результат у файл. Який найефективніший спосіб виконати завдання?


10
Використовуйте tacі grepдля досягнення того, що ви хочете.
Валентин Байрамі

1
На додаток до відмінних рішень, опублікованих у GNU grep, є --max-count (number)комутатор, який припиняє роботу після певної кількості збігів, що може бути цікавим для вас.
Ульріх Шварц

@ val0x00ff Ви можете поглянути на це запитання
c0rp

Чи знаєте ви, скільки у вас буде хітів? Коли ви думаєте, що ваш греп знайде 3 лінії, починайте обробляти та обертати назад.
Вальтер А

Відповіді:


46

tac / grep Рішення

tac file | grep whatever

Або трохи ефективніше:

grep whatever < <(tac file)

Час з файлом 500MB:

real    0m1.225s
user    0m1.164s
sys     0m0.516s

sed / grep Рішення:

sed '1!G;h;$!d' | grep whatever

Час з файлом 500MB: Аборт через 10+ хвилин.

awk / grep Рішення:

awk '{x[NR]=$0}END{while (NR) print x[NR--]}' file | grep whatever

Час з файлом 500MB:

real    0m5.626s
user    0m4.964s
sys     0m1.420s

perl / grep Рішення:

perl -e 'print reverse <>' file | grep whatever

Час з файлом 500MB:

real    0m3.551s
user    0m3.104s
sys     0m1.036s

2
sed, awkі perl(з цим методом) не в порядку, оскільки вони читали файл з самого початку, що дуже неефективно. Я гадаю, це tacробить правильно.
vinc17

1
@ vinc17 так, статистика часу вказує на те, що ви сказали.
хаос

2
@ val0x00ff Команда < <(tac filename)повинна бути такою ж швидкою, як і труба: в обох випадках команди працюють паралельно.
vinc17

7
Якщо ви збираєтеся досягти ефективності, то краще буде поставити tacпісля цього греп. Якщо у вас є файл 10 000 000 рядків, у якому є лише 2 збіги, tacпотрібно буде повернути лише 2 рядки, а не 10м. grepяк і раніше доведеться пройти всю справу в будь-якому випадку.
Патрік

3
Якщо ви поставите tacпісля grep, він буде читати з труби і тому не може шукати. Це зробить її менш ефективною (або повністю вийде з ладу), якщо кількість знайдених рядків буде великою.
jjanes

17

Це рішення може допомогти:

tac file_name | grep -e expression

3
tac- команда GNU. У більшості інших систем еквівалент є tail -r.
Стефан Шазелас

@ Stéphane: Принаймні деякі системи Unix tail -rобмежені невеликою кількістю ліній, це може бути проблемою.
RedGrittyBrick

1
@RedGrittyBrick, чи є у вас посилання на це, чи можете ви, будь ласка, сказати, у яких системах є таке обмеження?
Стефан Шазелас

@ StéphaneChazelas, tail -r /etc/passwdне вдається tail: invalid option -- 'r'. Я використовую coreutils-8.21-21.fc20.x86_64.
Крістіан Цюпіту

@ CristianCiupitu, як я вже сказав, у GNU є tac(і тільки GNU є tac) багато інших Союзів tail -r. GNU tailне підтримує-r
Stéphane Chazelas

10

Цей виходить, як тільки знайде перший збіг:

 tac hugeproduction.log | grep -m1 WhatImLookingFor

Далі наведено 5 рядків до та після перших двох матчів:

 tac hugeproduction.log | grep -m2 -A 5 -B 5 WhatImLookingFor

Пам’ятайте, що не використовуйте -i(нечутливий до регістру), якщо вам не доведеться, оскільки це уповільнить греп.

Якщо ви знаєте точний рядок, який ви шукаєте, тоді врахуйте fgrep(Fixed String)

 tac hugeproduction.log | grep -F -m2 -A 5 -B 5 'ABC1234XYZ'

9

Якщо файл дійсно великий, не може поміститися в пам'яті, я буду використовувати Perlз File :: ReadBackwards модуль з CPAN:

$ cat reverse-grep.pl
#!/usr/bin/perl

use strict;
use warnings;

use File::ReadBackwards;

my $pattern = shift;
my $rev = File::ReadBackwards->new(shift)
    or die "$!";

while (defined($_ = $rev->readline)) {
    print if /$pattern/;
}

$rev->close;

Тоді:

$ ./reverse-grep.pl pattern file

Перевага такого підходу полягає в тому, що ви можете налаштувати Perl, щоб робити все, що завгодно.
zzapper

1
@zzapper: Ця пам'ять також ефективна, оскільки коли вона читає файл рядок за рядком, а не файли в пам'яті, як tac.
cuonglm

хтось може додати підтримку для цього -m? Я хотів би перевірити справжні файли. Дивіться: gist.githubusercontent.com/ychaouche/…
ychaouche
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.