Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Override "null filehandle"

by BillKSmith (Monsignor)
on Sep 03, 2023 at 23:33 UTC ( [id://11154231] : perlquestion . print w/replies, xml ) Need Help??

BillKSmith has asked for the wisdom of the Perl Monks concerning the following question:

The documentation I/O Operators states that, in this case, the input from <> comes from "standard input". If this were exactly the same thing as "STDIN", the code below should work as expected and print "my input". (Try changing the input operator to <STDIN>.) Is there a way to override the "null filehandle" ?
use strict; use warnings; use autodie; open my $INPUT, '<', \"my input\n"; *STDIN = $INPUT; print <>;
Bill

Replies are listed 'Best First'.
Re: Override "null filehandle"
by choroba (Cardinal) on Sep 04, 2023 at 06:42 UTC
    The diamond operator reads from ARGV, not STDIN.
    open my $INPUT, '<', \"my input\n"; *ARGV = $INPUT; print <>;

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

      That's not quite true:

      % echo This is from STDIN|perl -e'print for <>' This is from STDIN % echo This is from ARGV > input1 % echo This is also from ARGV > input2 % perl -e'print for <>' input1 input2 This is from ARGV This is also from ARGV

      The <> operator looks first at at @ARGV and iterates line by line through each file specified as arguments to the script. But if there are no arguments (@ARGV is empty) then it falls back to reading from STDIN. This behaviour is documented in perlop, already linked to by the OP.

        The diamond operator reads from ARGV, not STDIN.
        That's not quite true

        choroba is correct though, in that <> is always equivalent to <ARGV>, as is described in the very documentation you referenced. The magical behavior you describe is not that of the <> operator in general, it is that of the ARGV filehandle, which modifies @ARGV in order for STDIN to be read automatically via the ARGV handle.

        Reworded for clarity, shortly after posting.

        <> always reads from ARGV. It's just that ARGV might in turn read from STDIN. Whether it does or not depends on @ARGV.

Re: Override "null filehandle"
by haukex (Archbishop) on Sep 04, 2023 at 10:54 UTC
    in this case, the input from <> comes from "standard input". If this were exactly the same thing as "STDIN"

    As per perlop and choroba's reply, <> is the same as <ARGV>.

    Is there a way to override the "null filehandle" ?

    That depends a bit on what you want to accomplish, could you describe that?* You've already gotten some replies on how to do this for a couple of cases, and I just wanted to add that messing with ARGV even more is possible, as I did in my module Tie::Handle::Argv. However, because of all of the trouble I had writing and testing that module, I can say that this is a pretty complicated thing to do, and I would not mess with <> if it can be avoided. Therefore your sample code makes me a bit nervous that you might be trying to do something that's not really advisable.

    * So for example, if you just want to mock <> for testing, it's better to do that by calling your script from another script and feeding it stuff to its STDIN, which can be done reliably, or just by placing test files (e.g. generated via File::Temp) in its @ARGV (Update: for example, you can localize *ARGV - yes, the whole typeglob).

Re: Override "null filehandle"
by tybalt89 (Monsignor) on Sep 04, 2023 at 02:37 UTC

    Like this ?

    #!/usr/bin/perl use strict; # https://www.perlmonks.org/?node_id=11154231 use warnings; use autodie; close STDIN; open STDIN, '<', \"my input\n"; print <>;
Re: Override "null filehandle"
by LanX (Saint) on Sep 04, 2023 at 00:29 UTC
    From the docs you linked to:

    > Here's how it works: the first time <> is evaluated, the @ARGV array is checked, and if it is empty, $ARGV[0] is set to "-", which when opened gives you standard input.

    So what's happening is that STDIN is re-opened.

    Did you try @ARGV = ($INPUT); instead?

    update

    just tested, doesn't work, this will try to use $INPUT as filename not handle...

    From the proposed alternatives, I like choroba's best with *ARGV = \$INPUT

    Cheers Rolf
    (addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
    Wikisyntax for the Monastery

Re: Override "null filehandle"
by BillKSmith (Monsignor) on Sep 06, 2023 at 14:14 UTC
    Thanks for all your replies. I believe that any one of them would have solved my problem. A few days ago I wanted to include code in my post Re^2: Why is my code producing weird output?. That code would have made no changes to the OP's code except to add input that explicitly showed the windows line endings. That would have duplicated his problem. Adding binmode STDIN, ':crlf'; would have fixed it. When I could not make the demo work, I settled for the verbal reply. Only later did I think to ask how I might have done it.

    Had I known all your answers, I probably would have chosen to close and reopen STDIN because it best describes my intention.

    Bill