2012-09-10 2 views
6

파일이펄, 비활성화 버퍼링 입력

:~$ cat fff | perl -e 'system("./1.pl")' 
qwerty 
asdf 
qwerty 
zxcvb 

은 그러나이 명령하지 않습니다 예상대로 작동 : 첫 번째 <STDIN> 한 줄이 아닌 모든 데이터를 읽습니다. <STDIN> 버퍼링을 해제하는 방법?

:~$ cat fff | perl -e '$_ = <STDIN>; system("./1.pl")' 
:~$ 
+0

당신은 확실 해요'cat fff | perl -e 'system ("./pl")' '이 내용을 인쇄합니까? 나를 위해서만'cat fff | 펄 1.pl' 않습니다. – tuxuday

답변

6

두 가지 펄 프로세스가 여기에 있습니다 - $_ = <STDIN>을 할당하고 system를 호출하는 첫 번째, 및 스트림의 첫 번째 라인은 첫 번째 프로세스에 의해 $_로 읽어 있지만 print <STDIN>

을 수행하는 두 번째, 뒤에서 Perl은 버퍼로 데이터를 채우고 스트림을 비워 둡니다.

이 목적은 무엇입니까? 여러분이 물어 보는 것을 염두에 두는 유일한 방법은 파일의 을 첫 번째 배열의 배열에 넣은 다음 첫 번째 줄을 제거하고 파이프의 나머지 부분을 두 번째 스크립트로 보내는 것입니다.

이 모든 것은 불필요한 것, 그리고 난 당신이 당신이 버퍼링 문제를 알고 말하는 때문에

는,이 작업을 수행 할 수있는 방법은

입니다 업데이트 근본적인 문제를 설명한다면 더 나은 방법이 확신 sysread을 사용하면 더 낮은 수준에서 파이프에서 읽고 버퍼링을 피할 수 있습니다.

이런 식으로 뭔가가

cat fff | perl -e 'while (sysread(STDIN, $c, 1)) {$_ .= $c; last if $c eq "\n"} system("./1.pl")' 

작동하지만 매우 잘못된 것 같습니다 무슨 일을로 추천 좋아하지 않아 난 당신이 내가 최근 했어 당신의 진짜 목표를

+0

한 줄 'tell'을 읽고 파일을 다시 열고 'seek'할 수 있습니다. – choroba

+0

@choroba : 예, 파이프가 아닙니다. – Borodin

+0

'$ cat fff | perl -ne'print $를 제외하고. == 1 '| ./1.pl'는 첫 줄을 제거하는 비 숙련 된 해결책이 될 것입니다. – amon

0

을 설명 텐데 각각 약 6 기가 바이트 인 여러 로그 파일을 구문 분석합니다. 버퍼링은 Perl이 배열에 STDIN을 할당 할 때 행복하게 6 기가 바이트를 메모리로 읽으려고 시도했기 때문에 문제였습니다 ... 그러나 단순히 그렇게 할 수있는 시스템 리소스가 없었습니다. 나는 단순히 줄 단위로 파일을 읽는 다음의 해결 방법을 생각해 냈다. 그렇지 않으면 거대한 메모리 블랙홀 버퍼링과 달리 모든 시스템 리소스를 명령하는 소용돌이를 피할 수 있었다.

참고 :이 스크립트는 6 기가 바이트 파일을 여러 개의 작은 파일 (크기는 각 출력 파일에 포함될 줄 수에 따라 결정됨)로 분할합니다. 흥미로운 비트는 while 루프와 로그 파일에서 변수로 한 줄을 할당하는 것입니다. 루프는 전체 파일에서 한 줄을 읽고 반복하여 반복하고 반복합니다. 결과, 거대한 버퍼링 ... 나는 단지 예제를 보여주기 위해 전체 스크립트를 그대로 유지했습니다 ...

#!/usr/bin/perl -w 
BEGIN{$ENV{'POSIXLY_CORRECT'} = 1;} 
use v5.14; 
use Getopt::Long qw(:config no_ignore_case); 

my $input = ''; 
my $output = ''; 
my $lines = 0; 
GetOptions('i=s' => \$input, 'o=s' => \$output, 'l=i' => \$lines); 

open FI, '<', $input; 

my $count = 0; 
my $count_file = 1; 
while($count < $lines){ 
    my $line = <FI>; #assign a single line of input to a variable 
    last unless defined($line); 
    open FO, '>>', "$output\_$count_file\.log"; 
    print FO $line; 
    $count++; 
    if($count == $lines){ 
     $count=0; 
     $count_file++; 
    } 
} 
print " done\n"; 

스크립트와 같은 명령 행에서 호출됩니다

(스크립트의 이름) -i (입력 파일) -o (출력 파일) -l (출력, 즉 파일 (라인 수의 크기)

정확하게 당신이 찾고있는 것이 아니더라도 몇 가지 아이디어를 줄 수 있기를 바랍니다. :)