How Do I Point a File Handle to STDOUT (or Another File Handle) In Perl?

前端 未结 5 1820
不知归路
不知归路 2021-01-31 18:19

I want to make a quick script that writes to a file if a file is given, or stdout if no file is given. It would be much easier for me to do this if I could start the script by p

5条回答
  •  猫巷女王i
    2021-01-31 18:54

    For the reader's sake (since OP already "got it working"):

    The Perl documentation, "perlopentut" (perldoc perlopentut) gives examples of opening an alternate filehandle directed to STDOUT, but it uses bareword filehandles, and the two-arg version of open, both of which are somewhat ancient. Damian Conway's book "Perl Best Practices" (as well as Perl::Critic, which is based on Damian's book) emphasizes using three arg opens and lexical filehandles (my $foo style filehandles). chromatic's "Modern Perl" also briefly mentions using lexical filehandles, and discourages barewords where practical. The three arg open is considered to be a safer form, as it limits exposure to shell injections. While the specific case here is low risk, it's still a good habit to default to the three-arg open.

    It takes careful reading of the examples shown in Perl's open documentation (perldoc -f open), and a little interpretation to notice the correct placement of the ampersand character in opening a duplicate filahandle directed to STDOUT when using the three-arg version of open. One might errantly assume that this should work: open my $fh, '>', '&STDOUT' or die $!;, mostly because it looks like a format we're used to seeing (ampersand preceding a symbol name). But that syntax isn't what open needs, and we're used to seeing it in an entirely different context: certain subroutine calls.

    The correct way to open a dupe to STDOUT with the three arg open is to combine the > and the & into the same second argument, and leave STDOUT bare, like this:

    use Modern::Perl;
    
    open my $fh, '>&', STDOUT or die "Bleah: $!";
    
    say $fh 'Printing alternate filehandle "$fh" worked.';
    say 'Implicitly printing to "STDOUT" also works.';
    

    Or passing STDOUT to open as a reference to the typeglob:

    open my $fh, '>&', \*STDOUT or ...
    

提交回复
热议问题