Perl 写入标准输出和打开文件句柄到"/开发/tty;?

Perl 写入标准输出和打开文件句柄到"/开发/tty;?,perl,stdout,tty,filehandle,Perl,Stdout,Tty,Filehandle,这两个例子有什么不同 #!/usr/bin/perl use warnings; use 5.012; my $str = "\x{263a}"; open my $tty, '>:encoding(utf8)', '/dev/tty' or die $!; say $tty $str; close $tty; open $tty, '>:bytes', '/dev/tty' or die $!; say $tty $str; close $tty; # ----------

这两个例子有什么不同

#!/usr/bin/perl
use warnings;
use 5.012;
my $str = "\x{263a}";


open my $tty, '>:encoding(utf8)', '/dev/tty' or die $!;
say $tty $str;
close $tty;

open $tty, '>:bytes', '/dev/tty' or die $!;
say $tty $str;
close $tty;

# -------------------------------------------------------

binmode STDOUT, ':encoding(utf8)' or die $!;
say $str;

binmode STDOUT, ':bytes' or die $!;
say $str;

不同之处在于,您正在编写两个不同的文件句柄(从Perl和您的程序的角度来看)独立的文件句柄

  • 第一个是打开到Unixy OS上特殊“设备”文件的文件句柄,该文件是“进程控制终端的同义词,(如果有)。(引自)。请注意,虽然它通常被认为是“屏幕”,但不一定是(例如,终端可以链接到串行端口的设备文件);而且它可能不存在或无法打开

  • 第二个是处理的文件,默认情况下与进程的文件描述符#1关联

乍一看,它们似乎是相同的,因为在典型情况下,Unix shell默认情况下会将其文件描述符#1(以及它启动时没有重定向的每个进程中的一个)与
/dev/tty
相关联

从Perl的角度来看,这两者没有任何共同之处,除了由于Unix shell的工作方式,这两者通常在默认情况下是相关联的

由于这种默认情况,两段引用代码的功能行为通常看起来是相同的,但这只是“偶然的”

在实际差异中:

  • /dev/tty
    不一定存在于非Unixy OSs上。因此,使用tty是高度不可移植的。Windows等价物是
    CON:
    IIRC

  • 一个程序的标准输出可以由调用该程序的人关联(重新定向)到任何东西。可以关联到文件,也可以是指向另一个进程STDIN的管道


您可以使用以下命令检查STDOUT是否连接到tty:

另一方面,请注意,通过显式关闭STDOUT文件句柄并重新打开它以指向
/dev/tty
,可以确保STDOUT写入
/dev/tty

close STDOUT or die $!;
open STDOUT '>:encoding(utf8)', '/dev/tty' or die $!;

除了DVK所说的之外,你可以通过说

perl -le 'open $o, ">:encoding(utf8)", "/dev/tty"; print "STDOUT"; print $o "/dev/tty"' > /dev/null

写入
STDOUT
会进入
/dev/null
,但写入
$o
会进入屏幕。

从交互式shell启动的程序通常会将标准输出写入终端,从而将
/dev/tty
STDOUT
呈现为相同的目标。但是,在某些情况下,
STDOUT
的输出可以写入其他目标

STDOUT
可以路由到单独的文件:

perl someprogram.pl > a/file
perl someprogram.pl >> a/file
STDOUT
可以路由到另一个程序的输入端

perl someprogram.pl | /usr/bin/mailx -s "Program Output" foo@bar.com

此外,该程序可以从非交互式shell(如cron作业)或从系统上运行的其他守护进程启动。这些程序的环境将无法访问
/dev/tty
设备,并且这些程序中的
STDOUT
将路由到其他地方(或任何地方)

其中一个写入/dev/tty,另一个写入STDOUT。这就是你想知道的吗?@JB-对于不太熟悉的人来说,这不是一个微不足道的区别Unix@DVK你说得对。当问题的要点是Unix时,我被问题的Perl方向弄糊涂了。谢谢你的启示@JB-耶!我是启蒙的源泉!现在我必须弄清楚我是否是荧光的。还要注意,有很多情况下根本不能使用
/dev/tty
(因为没有控制终端)-一个常见的例子是通过ssh调用命令,作为
ssh somehost somecommand
-默认情况下,ssh将连接STDIN、STDOUT和STDERR,但不创建实际的终端。@bdolan-correct(因此,在我引用的定义中添加了“,”if any“。或者,举一个简单的例子,在Windows上:)@JB-感谢
-t
编辑!顺便说一句,IIRC无法区分
/dev/tty
或任何其他终端设备。恐怕不能。可移植性很差,不是吗?再说一次,如果有人给我提供了一个连接到tty的标准输出,而不是进程的控制输出,我会假设他知道自己在做什么,然后让它溜走。
perl someprogram.pl | /usr/bin/mailx -s "Program Output" foo@bar.com