0

Perlスクリプトを発行すると、標準入力、たとえば

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

バグを含むスクリプトがあります。標準入力の最初の行を読み取り、その最初の行から何かを取得し、その後の読み取りで標準入力の 2 行目から n 行目までのみを解析します。

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 

スクリプトの開始時に標準入力の最初の行を正しく読み取り、ファイル ハンドルをリセットしてから、標準入力の 1 行目から n 行目をすべて読み取るにはどうすればよいですか?

ループの前に最初の行を保存して処理するための特別なケースを書くことができると思いwhileますが、標準入力とファイル入力の両方を処理できる、この問題に対するよりクリーンな解決策があることを願っています。

4

3 に答える 3

7

簡単な方法があります:

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

//do stuff with first line

do {
    //stuff
} while ($line = <FH>);
于 2009-12-11T06:15:37.487 に答える
2

編集:私の最初のアプローチの欠点はFH、リストを処理する前にすべての行をメモリにロードする必要があることです。このアプローチでは、open to scalar reference 機能 (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
}
于 2009-12-11T06:14:03.793 に答える
1

STDINのリセット(またはseek(0))はできないと思います。STDIN のような通常のファイル ハンドルではありません。実際にはファイルではないため、STDIN がリセット可能なバッファリングを行う必要があります。

1行目の読み取りと再利用を特別に処理する必要があると思います。

于 2009-12-11T06:14:09.680 に答える