当我发布一些标准输入的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
循环之前的第一行,但我希望有一个更清晰的解决方案来解决这个问题,它允许我处理标准输入和文件输入
答案 0 :(得分:7)
有一种简单的方法:
open (FH, "< $input") or die $?;
my $line = <FH>; // reads first line
//do stuff with first line
do {
//stuff
} while ($line = <FH>);
答案 1 :(得分: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
}
答案 2 :(得分:1)
我认为你不能为STDIN重置(或寻找(0))。它不是STDIN的普通文件句柄。由于它实际上不是文件,因此您需要STDIN执行可重置缓冲。
我认为你需要专门处理第1行的阅读和重复使用。