역그 리핑


44

정말 큰 텍스트 파일 (약 10.000.000 줄)이 있다고 가정 해 봅시다. 나는 grep결국 그것을하고 파일에 결과를 저장해야합니다. 작업을 수행하는 가장 효율적인 방법은 무엇입니까?


10
사용 tac하고 grep원하는 것을 달성 하십시오 .
Valentin Bajrami

1
게시 된 뛰어난 솔루션 외에도 GNU grep에는 --max-count (number)특정 수의 일치 후에 중단 되는 스위치가 있습니다.
Ulrich Schwarz

@ val0x00ff 질문을 살펴볼 수 있습니까
c0rp

당신은 얼마나 많은 명중을 가질 수 있는지 알고 있습니까? 당신의 grep이 3 개의 라인을 발견 할 것이라고 생각하면, grepping을 시작하고 나중에 반전하십시오.
Walter A

답변:


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 -e 'print reverse <>' file | grep whatever

500MB 파일 시간 :

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

2
sed, awkperl(이 방법을 사용하면) 처음부터 파일을 읽으므로 매우 비효율적입니다. 나는 그것이 tac옳은 일 이라고 생각합니다 .
vinc17

1
@ vinc17 예, 시간 통계는 당신이 말한 것을 가리 킵니다.
혼돈

2
@ val0x00ff < <(tac filename)파이프만큼 빨라야합니다. 두 경우 모두 명령이 병렬로 실행됩니다.
vinc17

7
효율성을 tac높이려면 grep 을 배치하는 것이 좋습니다 . 2 만 일치하는 10,000,000 개의 라인 파일이있는 경우 tac10m가 아닌 2 개의 라인 만 반전하면됩니다. grep여전히 모든 것을 어느 쪽이든 통과해야합니다.
Patrick

3
tac뒤에 넣으면 grep파이프에서 읽히므로 찾을 수 없습니다. 찾은 줄 수가 많으면 효율성이 떨어지거나 완전히 실패합니다.
jjanes

17

이 솔루션이 도움이 될 수 있습니다.

tac file_name | grep -e expression

3
tacGNU 명령입니다. 대부분의 다른 시스템에서 해당하는 것은 tail -r입니다.
Stéphane Chazelas

@ Stéphane : 최소한 일부 유닉스 시스템에서는 tail -r적은 수의 라인으로 제한됩니다. 이것은 문제가 될 수 있습니다.
RedGrittyBrick

1
@RedGrittyBrick, 당신은 그것에 대한 참조가 있습니까, 아니면 어떤 시스템이 그 제한이 있는지 말해 줄 수 있습니까?
Stéphane Chazelas

@ StéphaneChazelas가 tail -r /etc/passwd실패했습니다 tail: invalid option -- 'r'. coreutils-8.21-21.fc20.x86_64를 사용하고 있습니다.
Cristian Ciupitu

@CristianCiupitu, 내가 말했듯이, GNU에는 tac다른 많은 Unices가 가지고 있습니다 (GNU에만 전술이 있습니다) 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

-igrep을 느리게 할 필요가 없으면 사용하지 마십시오 (대소 문자 구분).

찾고있는 정확한 문자열을 알고 있다면 fgrep(고정 문자열) 을 고려하십시오.

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

9

파일이 정말 큰 경우, 내가 사용, 메모리에 맞지 않을 수 Perl파일 :: 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 : 메모리에서 slurp 파일 대신 한 줄씩 파일을 읽을 때 메모리 효율성이 뛰어납니다 tac.
cuonglm

누구든지 이것을 위해 -m 지원을 추가 할 수 있습니까? 실제 파일을 테스트하고 싶습니다. 참조 : gist.githubusercontent.com/ychaouche/…
ychaouche
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.