9

这两个例子有什么区别?

#!/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;
4

3 回答 3

13

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

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

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

乍一看,它们可能看起来是相同的,因为在典型情况下,Unix shell 默认将其文件描述符#1(因此它启动的每个进程之一没有重定向)与/dev/tty.

从 Perl 的角度来看,这两者没有任何共同之处,除了由于 Unix shell 的工作方式,这两者通常最终默认关联。

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

在实际差异中:

  • /dev/tty不一定存在于非 Unixy 操作系统上。因此,使用 tty 非常不便携。Windows 等效项是CON:IIRC。

  • STDOUT程序的任何人都可以将程序关联(重新定向)到任何调用程序的人。可以关联到一个文件,可以是另一个进程的 STDIN 的管道。


-t您可以使用操作符检查您的 STDOUT 是否连接到 tty :

if ( -t STDOUT ) { say 'STDOUT is connected to a tty' }

/dev/tty另外,请注意,您可以通过明确关闭 STDOUT 文件句柄并重新打开它以指向:来确保您的 STDOUT 写入/dev/tty

close STDOUT or die $!;
open STDOUT '>:encoding(utf8)', '/dev/tty' or die $!;
于 2011-01-12T12:05:34.007 回答
4

除了DVK所说的,你可以通过说看到简单的区别

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

写入到STDOUT/dev/null但写入到$o屏幕。

于 2011-01-12T13:09:13.440 回答
4

从交互式 shell 启动的程序通常会将标准输出写入终端,该终端将呈现/dev/ttySTDOUT作为相同的目的地。但是有几种情况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在这些程序中将被路由到其他地方(或无处)。

于 2011-01-12T17:13:34.350 回答