Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
611 views
in Technique[技术] by (71.8m points)

perl - What type is STDOUT, and how do I optionally write to it?

Does STDOUT have a "type"?

printf STDERR ("STDOUT = %s
", STDOUT);
printf STDERR ("*STDOUT = %s
", *STDOUT);
printf STDERR ("\*STDOUT = %s
", *STDOUT);

Produces:

STDOUT = STDOUT
*STDOUT = *main::STDOUT
*STDOUT = GLOB(0x600078848)

I understand the *main::STDOUT and GLOB(0x600078848) entries. The "bareword" one leaves me curious.

I'm asking because I want to pass a file handle-like argument to a method call. In 'C', I'd use a file descriptor or a File *. I want it to default to STDOUT. What I've done is:

$OUT_FILE_HANDLE = *STDOUT;
if(@ARGV > 0 ) {
    open($OUT_FILE_HANDLE, ">", "$ARGV[0]") or die $!;
}

It works, but I don't know exactly what I've done. Have I botched up STDOUT? I suspect I have "ruined" (overwritten) STDOUT, which is NOT what I want.

Please pardon the compound question; they seemed related.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Create a lexical filehandle to be a copy of STDOUT and manipulate that as needed

sub manip_fh { 
    my ($fh) = @_;
    say $fh "hi";                              # goes to STDOUT
    open my $fh, '>', 'a_file.txt' or die $!;  # now it's to a file
    say $fh "hello";
}

open my $fh, '>&', STDOUT;  # via dup2

manip_fh($fh);

say "hi";  # still goes where STDOUT went before being dup-ed (terminal)

This new, independent, filehandle can then be reopened to another resource without affecting STDOUT. See open.

The $OUT_FILE_HANDLE = *STDOUT; from the question creates an alias and so the STDOUT does indeed get changed when the "new" one changes. You can see that by printing the typeglob

our $NEW = *STDOUT;
say *{$main::NEW};    #--> *main::STDOUT

or by printing the IO slot from the symbol table for both

say for *{$main::NEW}{IO}, *{$main::{STDOUT}}{IO};

and seeing (that the object stringifies to) the same (eg IO::File=IO(0x1a8ca50)).

When it's duped using open with mode >& as in the first code snippet (but as global our) it prints *main::NEW, and its IO::File object is not the same as for STDOUT. (Make it a global our so that it is in the symbol table for this check, but not for real use; it's much better having a lexical.)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...