2009-12-11 1 views
0

Perl 스크립트에 몇 가지 표준 입력을 발행하면 (예 :Perl에서 표준 입력을받는 파일 핸들을 재설정하려면 어떻게해야합니까?

$ awk '{print $1"\t"$2}' foo.txt | myScript.pl 

버그가 포함 된 스크립트가 있습니다. 그것은 표준 입력의 첫 줄을 읽 첫 번째 줄에서 무언가를 가져오고 만 이후 읽기에 표준 입력의 N을 통해 선 2 구문 분석 :

open (FH, "< $input") or die $?; 
my $firstLine = <FH>; // reads first line 

... 

while (my $line = <FH>) { 
    // reads lines 2 through n 
} 
close (FH); 

그래서 내가하려고하는이 스크립트에 seek 문을 추가 파일의 시작 부분에 파일 핸들을 다시 설정 :

use Fcntl qw(:seek); 

... 

open (FH, "< $input") or die $?; 
my $firstLine = <FH>; // reads first line 
seek (FH, 0, SEEK_SET) or die "error: could not reset file handle\n"; // should reset file handle 

... 

while (my $line = <FH>) { 
    // reads lines 1 through n (in theory) 
} 
close (FH); 

seek 문을 추가하면 파일 입력을 위해 작동하지만 표준 입력하십시오. 스크립트 오류로 충돌 :

error: could not reset file handle 

가 어떻게 올바르게, 스크립트의 시작 부분에 표준 입력의 첫 번째 줄을 읽은 파일 핸들을 다시 설정 한 후 표준 입력의 N을 통해 모든 라인 1을 읽을 수 있습니까?

while 루프가 있기 전에 첫 번째 줄을 저장하고 처리하는 특별한 경우를 작성할 수 있다고 생각합니다.하지만 표준 입력과 파일 입력을 모두 처리 할 수있는이 문제를 해결할 수있는 더 깨끗한 솔루션이 필요합니다.

답변

7

쉬운 방법있다 :

open (FH, "< $input") or die $?; 
my $line = <FH>; // reads first line 

//do stuff with first line 

do { 
    //stuff 
} while ($line = <FH>); 
+0

물론! 나는 do-while에 대해 완전히 잊었다. 매우 우아합니다. 고마워요. –

+1

다음/마지막에는 do {}가 블록으로 표시되지 않는다는 것을 기억하십시오. 표준 해결책에 대해서는 http://perldoc.perl.org/perlsyn.html#Statement- Modifiers를 참조하십시오. – ysth

2

편집 : 내 첫 번째 방법의 단점은 목록을 처리하기 전에 FH의 모든 줄을 메모리에로드해야한다는 것입니다. (5.8.0 이후 가능) 스칼라 참조 기능에 오픈을 사용하는이 방법은, 그 문제가되지 않습니다

my $firstline = <FH>; 
open(my $f1, '<', \$firstline); 

... 

while (my $line = <$f1> || <FH>) { 
    # process line 1 through n 
} 

을 대한 방법 :

for my $line ($firstline, <FH>) { 
    # process lines 1 through n 
} 
+0

나는'사용하여 좋아 while' 나는 매우 큰 파일을 처리하기 때문이다. 'for'를 사용하는 것은 앞서 언급했듯이 모든 입력 데이터를 처리하기 전에 메모리에 저장해야합니다. –

1

것은 당신을 생각하지 않는다 STDIN을 재설정 (또는 탐색 (0)) 할 수 있습니다. STDIN과 같은 일반 파일 핸들이 아닙니다. 실제로 파일이 아니기 때문에 STDIN이 재설정 가능한 버퍼링을 요구합니다.

난 당신이 독서를 처리하고 다시 사용하여 라인 1 특별히으로해야합니다 생각합니다.

+0

문제는 그것이 STDIN이 아니라 파일이 아니라는 것입니다. 파이프 또는 다른 탐색 불가능한 유형 인 다른 파일 핸들에서 찾기가 실패합니다. seek이 파일이라면 STDIN에서도 성공할 것입니다. 예를 들면 다음과 같습니다 :'seq 9> foo; perl-we'seek STDIN, 12, 0; print scalar <> ' ysth