这两个例子之间有什么区别?
#!/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;
答案 0 :(得分:13)
不同之处在于您正在写两个不同和(从Perl和您的程序的角度来看)独立文件句柄。
第一个是在Unixy OS上打开一个特殊“设备”文件的文件句柄,它是“进程控制终端的同义词,,如果有的话”(引自this Linux document)。请注意,虽然它通常被认为是“屏幕”,但它不一定是(例如,该终端可以链接到串口的设备文件);它可能不存在或不可开放。
第二个是默认关联的文件,文件描述符#1用于该过程。
由于在典型情况下,Unix shell默认情况下会将其文件描述符#1(因此在没有重定向的情况下启动的每个进程中的一个)与{{{}相关联,因此它们看起来可能相同。 1}}。
这两者从Perl的角度来看没有任何共同之处,除了这两个通常由于Unix shell工作方式而默认最终关联的事实。
由于此默认值,两个引用代码段的功能行为通常会相同,但这只是“偶然”。
实际差异:
/dev/tty
不一定存在于非Unix操作系统上。因此使用tty非常不便携。 Windows等效项为/dev/tty
IIRC。
CON:
可以被任何调用该程序的人关联(重定向)到ANYTHING。可以与文件关联,可以是到另一个进程的STDIN的管道。
您可以使用-t
operator检查您的STDOUT是否已连接到tty:
STDOUT
另外请注意,您可以通过明确关闭STDOUT文件句柄并重新打开它以指向if ( -t STDOUT ) { say 'STDOUT is connected to a tty' }
来确保您的STDOUT写入/dev/tty
:
/dev/tty
答案 1 :(得分:4)
除了DVK所说的,你可以通过说
看到简单的区别perl -le 'open $o, ">:encoding(utf8)", "/dev/tty"; print "STDOUT"; print $o "/dev/tty"' > /dev/null
对STDOUT
的写入转到/dev/null
,但写入$o
会转到屏幕。
答案 2 :(得分:4)
从交互式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
将被路由到其他地方(或无处)。