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

See code below... is the current selected filehandle (usually STDOUT, but not in the magic while(<>)) some perl default variable? I looked in perlvar but didn't see anything. How does this inplace edit magic work? Where is it documented?
use strict; use warnings; use Test::More qw(no_plan); #create a.txt contining "a" open F, "> a.txt"; print F "a"; close F; #fails because no substitution was made #prints to STDOUT process_file(); local $^I = ".bak"; #now it works. #prints to "a.txt" as we want. But how does it know to print there? write_and_read_file(); #ok sub process_file { @ARGV = qw(a.txt); local $/; # slurp it #changes a.txt so contains "b" #the diamond operator operates on @ARGV by default while (<>) { #$_ now contains the entire file, alter at will s/a/b/g; #How does the print operator know what file handle to print to +? #Was this selected somewhere by magic? #Where is this documented / explained? print; } #need to reset @ARGV, I guess it got wiped out somewhere in that w +hile. @ARGV = qw(a.txt); while (<>) { is($_,"b"); } }
Outputs:
bnot ok 1 # Failed test (diamond.pl at line 35) # got: 'a' # expected: 'b' Undefined subroutine &main::write_and_read_file called at diamond.pl l +ine 15, <> line 1. 1..1 # Looks like you failed 1 tests of 1. # Looks like your test died just after 1.
(Inspired by Re: Shell trick to edit many files with perl)

Replies are listed 'Best First'.
Re: how does print know what filehandle to use, when in a diamond in-place edit loop?
by merlyn (Sage) on Aug 09, 2005 at 15:40 UTC
    #How does the print operator know what file handle to print to +? #Was this selected somewhere by magic? #Where is this documented / explained?
    perldoc perlrun says:
    From the shell, saying $ perl -p -i.orig -e "s/foo/bar/; ... " is the same as using the program: #!/usr/bin/perl -pi.orig s/foo/bar/; which is equivalent to #!/usr/bin/perl $extension = '.orig'; LINE: while (<>) { if ($ARGV ne $oldargv) { if ($extension !~ /\*/) { $backup = $ARGV . $extension; } else { ($backup = $extension) =~ s/\*/$ARGV/g; } rename($ARGV, $backup); open(ARGVOUT, ">$ARGV"); select(ARGVOUT); $oldargv = $ARGV; } s/foo/bar/; } continue { print; # this prints to original filename } select(STDOUT); except that the -i form doesn't need to compare $ARGV to $ +oldargv to know when the filename has changed. It does, however, +use ARGVOUT for the selected filehandle. Note that STDOUT is +restored as the default output filehandle after the loop.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

Re: how does print know what filehandle to use, when in a diamond in-place edit loop?
by gellyfish (Monsignor) on Aug 09, 2005 at 15:38 UTC

    The inplace edit case uses the special filehandles ARGV (for input) and ARGVOUT (for output) these are document in perlvar

    /J\

Re: how does print know what filehandle to use, when in a diamond in-place edit loop?
by ysth (Canon) on Aug 11, 2005 at 10:05 UTC
    You can get the current selected filehandle by:
    select(my $selected = select(my $dummy)); print $selected;
    You may get the name of a glob (e.g. "main::ARGVOUT") or a globref, depending on what was passed to select before.