<>读取非空@ARGV后挂在STDIN上

时间:2019-01-11 18:45:31

标签: perl

下面的代码是perl程序的框架,用于处理具有结构化文本的某些文件。如果通过STDIN提供输入,该程序将按预期工作:

./process_files.pl < some_file

但是如果要处理的文件是命令行参数,它将挂起:

./process_files.pl some_file

在strace下运行此命令表明,读取文件后,程序卡在了read(0, ...)上。可以肯定的是,在终端上输入Ctrl-D可以解开程序,然后程序运行完成。

为什么从非空@ARGV读取后,perl为什么要在STDIN上等待?

perl代码:

#!/usr/bin/perl

sub meta
{
    while ( <> )
    {
        return if m!</META>!;
        # process metadata line
    }
}

sub data
{
    while ( <> )
    {
        return if m!</DATA>!;
        # process data line
    }
}

while ( <> )
{
    meta if m!<META>!;
    data if m!<DATA>!;
}

# post processing here

exit 0;

附录:正在处理的文本文件的行具有以下模式:

lines (ignored)
<META>
meta data lines (processed)
</META>
lines (ignored)
<DATA>
data lines (processed)
</DATA>
optional lines (ignored)

1 个答案:

答案 0 :(得分:4)

问题是您在ARGV返回EOF后一直读取该信息。

ARGV进行读取会在打开@ARGV时将其删除,因此@ARGV在第二次查询时就为空,从而导致从STDIN读取数据。

您的程序归结为以下内容:

print "\@ARGV: @ARGV\n";     # Outputs: @ARGV: file.txt
while (<>) { }               # Reads from file.txt.
print "\@ARGV: @ARGV\n";     # Outputs: @ARGV:
while (<>) { }               # Reads from STDIN.

顺便说一句,您永远不要期望返回EOF的文件句柄继续返回EOF。这并非总是如此。例如,POSIX系统上的终端句柄并非如此。