2012-09-21 2 views
0

Windows에서 Perl을 사용하여 big * .gz 파일을 구문 분석하려고합니다.Perl - Windows에서 거대한 * .gz 파일 구문 분석

my $cmd = "zcat $dir/$file|"; 
open FILE, $cmd or die "$cmd:$!"; 

while (<FILE>) { 
. 
. 
. 
} 

을하고 그것을 잘 작동합니다 :

솔라리스에서 나는 건설 다음 사용할 수 있어요. Windows에서 IO::Zlib 모듈을 사용하고 있습니다. 예 :

my $fh = IO::Zlib->new("$file", "rb"); 
while (my $line = $fh->getline()) { 
. 
. 
} 

그러나 메모리가 부족합니다. (나는 시스템에 4GB RAM을 가지고있다.) 큰 * .gz 파일을 구문 분석하는 다른 방법이 있습니까?

+0

처리하기 전에 압축을 풀 수없는 이유는 무엇입니까? 디스크 공간이 부족합니까? –

+0

루프 내부의 다른 작업을 수행합니까? 또한 파일에 외부 줄 끝이 있으면 perl이 파일을 slurp 처리 할 수 ​​있습니다 (IO :: Zlib은'$ /'대신 명시 적 \ n을 사용합니다). – TLP

답변

2

Gzip for Windows (zcat 포함)을 설치하지 않는 이유는 무엇입니까? 메모리 문제 외에도 gzip의 배관이 IO::Zlib을 사용하는 것보다 빠르다는 것을 발견했습니다. ($fh->getline은 메서드 호출이며 Perl의 메서드 호출이 가장 빠르지 않으며 gzip을 외부 적으로 실행하면 멀티 태스킹을 활용하므로 멀티 코어 컴퓨터가 일반적이라는 사실을 눈치 챌 수 있습니다.

GnuWin은 어떤 이유로 Windows에서 실제로 작동하지 않는 쉘 스크립트로 zcat을 제공합니다. 하지만 zcat 대신에 gzip -cd을 사용할 수 있습니다 (Unix 플랫폼에서도 작동 함).

+0

흠, 좋은 소리. 나는 그것을 시도 할 것이다. 창문에서 gzip으로 파이핑하는 법을 말해 줄 수 있다고 생각하니? – taiko

+0

Solaris에서 사용한 것과 같은 방법입니다. 'PATH'에'zcat'을 써야합니다 (Solaris와 동일). – cjm

+0

GnuWin32를 설치했고, bin 디렉토리에 zcat이 있고, PATH가 업데이트 된 것을 볼 수 있지만, 펄 스크립트에서 zcat을 호출하는 법을 모르겠습니다. 오류 메시지 'c :/progra ~ 1/GnuWin32/bin/zcat'이 내부 또는 외부 명령, 작동 가능 프로그램 또는 배치 파일로 인식되지 않습니다. – taiko

2

IO::Zlib->getline은 "라인"으로 읽습니다. 한 줄은 줄 끝으로 끝나는 한 묶음의 데이터로 정의됩니다. Perl의 "\ n"은 운영 체제에 따라 변경됩니다. Unix (Solaris 및 OS X 포함)에서는 012 (줄 바꿈 문자)입니다. Windows에서는 015 012 (캐리지 리턴 + 개행)입니다.

파일에 Unix 개행 문자가있는 경우 IO::Zlib->getline은 Windows에서 실행할 때 Windows 개행을 찾습니다. 전체 파일을 메모리로 읽으려고합니다. 일반적으로 $/, "입력 레코드 구분 기호"를 "행 끝"으로 설정하면 \015\012이되지만 IO :: Zlib (Compress::Zlib을 통해)은 이전 버전과의 호환성을 위해 $/을 지원하지 않습니다.

다행히도이 모든 혼란은 IO :: Compress 및 IO :: Uncompress로 재 작성되었습니다. IO::Uncompress::Gunzip을 사용하면 Compress :: Zlib가 이미 설치되어 있습니다.

use IO::Uncompress::Gunzip; 

# A block to isolate the local $/ 
{ 
    my $fh = IO::Uncompress::Gunzip->new($file); 

    # the file being read has Unix newlines 
    local $/ = "\012"; 

    # As an added bonus, the object works as a filehandle. 
    while(my $line = <$fh>) { 
     ... 
    } 
} 
+0

이것이 효과가 있지만 마지막으로 몇 년 전 기가 바이트 크기의 파일을 벤치마킹 한 결과 외부에서 'gzip'프로세스로 파이프를 여는 것보다 속도가 훨씬 느려졌습니다 (아마도 필자의 대답에서 언급 한 이유 때문일 것입니다). 객체를 파일 핸들로 사용할 때조차도 Perl은 여전히 ​​후드에서 메소드 호출을 사용합니다. – cjm

+0

@cjm OP는 가장 빠른 질문을하지 않았고 왜 작동하지 않는지 물었습니다. zcat을 사용하여 줄 바꿈 문제를 해결하지 못하면 ''은 Windows에서 Unix 줄 바꿈을 사용하는 경우 전체 파일을 계속 스 루핑합니다. '$ /'는 여전히 수정되어야합니다. 마이크로 퍼포먼스를 원한다면, OP가 라인을 가지고 무엇을하고 있는지 알지 못한다. C 프로그램을 사용하라. 환경 간 호환성을 원하면 Perl 모듈을 사용하십시오. 그들은 솔라리스와 윈도우 모두에서 작업하고 있기 때문에 교차 환경이 중요하다고 생각합니다. YMMV. – Schwern

+0

사실, 외부'gzip' *을 사용하면 개행 문제가 해결됩니다. Windows에서 Perl은 기본적으로': crlf' 레이어를 적용합니다.이 레이어는 CRLF 또는 LF 라인 끝을 입력으로 허용합니다 (이전을 일반 LF로 변환). – cjm