2012-12-05 2 views
1

아래 예와 같이 perl grep을 사용하고 있습니다. "bfh"는 읽기 명령으로 열린 파일 핸들입니다. 대신 파일 핸들 "BFH"의perl grep function

@searchResults = grep {/,\s*${searchRecId}\s*,\s*${searchSwId}\s*/} <$bfh>; 

, 나는 유닉스 grep 명령처럼, directily 경로와 파일 이름을 줄 수 있습니까? 내가하고 싶다면, 어떤 변화를 만들어야합니까? 아래의 코드가 정확합니까?

@searchResults = grep {/,\s*${searchRecId}\s*,\s*${searchSwId}\s*/} /tmp/test.out 

파일 핸들 또는 배열을 제공하고 싶지 않습니다. 난 그냥 유닉스 grep 명령처럼 그것을하고 싶다.

1000 개의 파일을 덮어 쓸 것입니다. 내가 100000 라인 파일을 읽을 때 grep에 관해서 각 라인은 파일 이름을 가지고 있고 싶다. 1000 파일 핸들을 열고 해시 맵을 유지하는 대신에 직접적으로 파일 이름을 갖고 싶다.

답변

1

당신은 할 수 :

use Slurp; 
my $filename = 'my/file/name'; 
@searchResults = grep {/,\s*${searchRecId}\s*,\s*${searchSwId}\s*/} 
        slurp $filename; 

이 메모리에 파일을 읽을 것입니다,하지만.

+0

이 질문에 대답하지 않습니다. – Borodin

+0

정보를 보내 주셔서 감사합니다 – Arav

3

map을 통해 처리 할 수 ​​있습니다. 이 잘린 예를 들어, 현재 디렉토리에 *.dat을 greps : 많은 선으로 많은 파일을 처리 할 때

그러나
my @searchResults = grep { 
    /,\s*${searchRecId}\s*,\s*${searchSwId}\s*/ 
} map { 
    sub { 
     my @ret; 
     if (open my $fh, "<", shift) { 
      @r = <$fh>; 
      close @fh; 
     } 
     return @ret; 
    }->($_); 
} glob "*.dat"; 

, 이것은 차선의 방법입니다! 당신이 쉘에있어 경우 ack 유틸리티를 체크 아웃,

my @searchResults; 
opendir(my $dh, '.') or die "error opening current directory: $!"; 
while (my $file = readdir $dh) { 
    next unless -f $file; 
    next if $file !~ /\.dat$/; 
    if (open my $fh, '<', $file) { 
     while (my $line = <$fh>) { 
      if (/,\s*${searchRecId}\s*,\s*${searchSwId}\s*/) { 
       push @searchResults, $line; 
      } 
     } 
     close $fh; 
    } else { 
     die "error processing $file: $!"; 
    } 
} 
closedir $dh; 

그리고 : 여기에 같은 일을하고 덜 메모리 욕심 방법입니다.

+0

정보를 제공해 주셔서 감사합니다. 1000 개의 파일을 덮어 쓸 것입니다. 내가 100000 라인 파일을 읽을 때마다 grep에 관해서는 파일을 엽니 다. 각 grep에 대해 파일 핸들을 여는 것이 효율적입니까? 닫기 파일 핸들은 어디에서 발생합니까? – Arav

+0

관측에 감사드립니다. @Arav! 핸들이 제대로 닫힐 수 있도록'map {}'예제를 수정했습니다. 또한 모든 것을 RAM에로드하는 데 의존하지 않는 빠른 반복 구현을 추가했습니다. – creaktive

+0

내가 백틱을 사용하는 유닉스 Grep을 사용한다면 더 빠를 것입니다. @searchresult ='grep searchrec/tmp/testfile'. – Arav