如何重置在 Perl 中接收标准输入的文件句柄?

问题描述 投票:0回答:3

当我发出 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
循环之前的第一行,但我希望有一个更清晰的解决方案来解决这个问题,使我能够处理标准输入和文件输入。

perl file-io seek
3个回答
7
投票

有一个简单的方法:

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

# do stuff with first line

do {
    # stuff
} while ($line = <FH>);

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
}

1
投票

我认为您无法重置(或寻求(0))STDIN。 它不是标准输入那样的普通文件句柄。由于它实际上不是一个文件,因此您需要 STDIN 进行可重置缓冲。

我认为你需要专门处理第1行的读取和重用。

© www.soinside.com 2019 - 2024. All rights reserved.