我写了一些代码,我认为我正在测试是否存在STDIN。 但是代码与我的预期相反。
这是我写的代码,我称之为zit
#!/usr/bin/perl
use strict 'vars';
my @a = @ARGV ? @ARGV : "EMPTY";
printf " command line arguments: "%s" as expectedn", @a;
if ( -t STDIN )
{
print " ( -t STDIN ) returns TRUEn";
}
else
{
print " ( -t STDIN ) returns FALSEn";
print " But, I can iterate over <STDIN>! Huh?? Behold:n";
}
以下是我的想法:
zit <(echo a;echo b)
会导致( -t STDIN )
FALSE
。zit < <(echo a;echo b)
将导致( -t STDIN )
TRUE
。
因此,为了弄清楚可能发生了什么,我通过添加while
循环来修改if-then
代码(根据我的理解,我将其放在我认为应该产生问题的地方)。
#!/usr/bin/perl
use strict 'vars';
my @a = @ARGV ? @ARGV : "EMPTY";
printf " command line arguments: "%s" as expectedn", @a;
if ( -t STDIN )
{
print " ( -t STDIN ) returns TRUEn";
}
else
{
print " ( -t STDIN ) returns FALSEn";
print " But, I can iterate over <STDIN>! Huh?? Behold:n";
while ( <STDIN> )
{
print ">> $_";
}
}
这是此代码的输出
zit <(echo a;echo b)
具有以下输出
command line arguments: "/dev/fd/63" as expected
( -t STDIN ) returns TRUE
zit < <(echo a;echo b)
具有以下输出
command line arguments: "EMPTY" as expected
( -t STDIN ) returns FALSE
But, I can iterate over <STDIN>! Huh?? Behold:
>> a
>> b
我对此感到非常困惑。 这不是我所认为的那样。 如果( -t STDIN )
为假,为什么while
循环有效?
有人可以解释一下这里发生了什么吗?
我已经重新编辑了之前的这篇文章,以减少混乱。
use strict 'vars';
你为什么要这么做?您实际上应该只是use strict;
并启用所有三个限制,而不仅仅是vars
。您还应该use warnings;
.
如果您检查perldoc -f -t
,您将看到文档说:
-t Filehandle is opened to a tty.
换句话说,它不是测试是否存在 STDIN(总是有一个 STDIN(除非你的父进程很顽皮并在启动你之前关闭了它)),而是 STDIN 是否指的是终端(缩写"tty"最初指的是电传打字机,但当它们被文本终端和后来的终端仿真器(如 xterm)取代时,这个名字有点卡住了)。在 C 术语中,它对应于对isatty
的调用。
在您的第一个示例中,您有zit <(echo a;echo b)
.<( ... )
表示法使 bash 运行指定的命令,并将其 STDOUT 重定向到管道。然后,它将<( ... )
替换为引用管道(读取结束)的文件名。
具体来说,它运行zit /dev/fd/63
(其中文件描述符 63 是指管道的读取端,其写入端由echo a; echo b
馈送)。STDIN没有任何反应,所以zit
从shell继承了它的标准流,所以STDIN引用了一个终端,这就是-t STDIN
返回true的原因。
在第二个示例中,您有zit < <(echo a;echo b)
.这非常相似,但现在生成的命令是zit < /dev/fd/63
.< FILE
表示法告诉 shell 打开指定的文件进行读取并将 STDIN 重定向到该文件。
因此,它运行zit
(没有任何命令行参数),STDIN 连接到管道(其另一端由echo a; echo b
馈送)。这实际上与( echo a; echo b ) | zit
相同。这里 zit 的 STDIN 指的是管道,而不是终端,所以-t STDIN
返回 false。当然,您仍然可以从中读取:您可以从中读取的大多数内容都不是终端,例如普通文件,管道或套接字。