views:

897

answers:

5

Ok, I have a bit of an issue here. I realize that I don't need to set a $handle to *::HTML to get this snippet to work, however this code is taken out of context from its use and I do in fact need this to work with the $handle. The output I am receiving is below the snippet however the output I want is for the file.html to contain "what\nsometext1\nsometext2\n".

open(HTML, ">file.html");
$handle = \*::HTML;
print $handle "what\n";

open(READ, "< somefile.txt"); #somefile.txt contains sometext1\nsometext2\n
while(<READ>)
{
    print $handle;
}
close READ;
close HTML;

file.html is left with the output "what" and GLOB(0x6278b0)GLOB(0x6278b0) is printed to terminal window.

+1  A: 

Nevermind, i figured it out, I need the $_ after $handle for this. Why is this the case though?

print is context sensitive -- with a single argument, it assumes you want to print to STDOUT; with two or more arguments, it takes the first one to be the glob you want to print on. And because you specified an argument to print already, $handle, it won't use $_ as a default argument.
Andrew Barnett
+7  A: 

If you look at the documentation for print you will see that there are three valid ways to call print:

  • print FILEHANDLE LIST
  • print LIST
  • print

Only the last version prints $_ implicitly. The reason for this is simple, Perl can't tell if you mean to print the filehandle or to the filehandle without more information (the whitespace separating the filehandle and the list). Printing the filehandle (rather than to it) is the most flexible method, so they chose that resolution of the ambiguous case.

Chas. Owens
Actually, "print HANDLE" uses $_ as well, but perl parses an ambiguous scalar as "print LIST" instead. (And "print {$fh}" is a syntax error.)
Michael Carman
+3  A: 

When you use scalar variables to hold filehandles you have to help Perl understand how to parse the expression. Saying print $var is ambiguous. It could mean either of the following:

print STDOUT $var;  # print the contents of $var to STDOUT
print {$var} $_;    # print the contents of $_ to the handle $var

Perl picks the former. If you want the latter, you need to make it explicit by bracketing the filehandle to disambiguate it.

Furthermore, Perl only uses the default variable $_ when you don't supply any arguments for what to print. Because of how print $var is interpreted, $_ isn't used.

Michael Carman
+3  A: 

Perl's print operator does allow omission of LIST in all cases. Consider:

$ perl -le '$_ = "foo!"; print STDOUT'
foo!

But that looks to the parser like a filehandle—unlike print $scalar, which could be anything at runtime. If you're unsure of the parse for a bit of code, feed it through B::Deparse, as in

$ perl -MO=Deparse,-p try
while (defined(($_ = <READ>))) {
    print($_);
    print($handle);
    print(STDOUT $_);
}

As written, the loop contains three calls to print: print, print $handle, and print STDOUT.

To get close to what you want, you might use select:

my $oldfh = select $handle;

while(<READ>)
{
    print;
}

select $oldfh;

Note that select returns the previously-selected filehandle, and the code above saves it so as to put things back where we found them afterward.

Greg Bacon
+1  A: 
use strict;
use warnings;

open( my $html, '>', "file.html" );
print $html "what\n";

open( my $read, '<', "somefile.txt" ); #somefile.txt contains sometext1\nsometext2\n

while( my $line = <$read> )    {
    print {$handle} $line;
}

close $read;
close $html;
Brad Gilbert