-2

I'm running the following code:

open my $fh, "<", $file;

$/ = undef;
my $report = <$fh>;
$/ = "\n";

close $fh;

print("$report\n\n");

$file refers to a text file that looks like this:

a    1
b    2
c    3

I ran this code on two different Linux boxes. One of them gave me the expected output (exactly as it appears in the text file). The other one gave me this instead:

GLOB(0x80f1174)

... which effectively prevents me from further manipulating the contents.

I checked the Perl versions - the one the gives me the expected output is 5.10, while the other one is 5.8. However, I have executed the exact same code against similar files in the past with 5.8 that worked.

I've also tried converting the file from DOS to UNIX via :set ff=unix, but to no avail.

kaspnord
  • 1,403
  • 2
  • 18
  • 28
  • 1
    You would get output like `GLOB(0x80f1174)` if line 4 said `my $result = $fh` rather than `my $result = <$fh>`. – mob Apr 02 '12 at 15:41
  • @mob I double-checked my code - it's using <$fh>. – kaspnord Apr 02 '12 at 15:47
  • @kaspnord, Then triple-check. Maybe you aren't executing the file you think you are executing. – ikegami Apr 02 '12 at 16:03
  • That output would also happen if `<$fh>` was getting interpreted as `glob($fh)` instead of `readline($fh)` for some reason. Is the code use a simple scalar for the filehandle like `$fh` or is the actual filehandle more complicated (`$fh[7]`, `$handle{$filename}`, `&function_that_returns_filehandle(42)`, etc.)? – mob Apr 02 '12 at 16:07
  • @ikegami I just triple-checked. Copied the script file and text file again from the working machine to the other machine. No change. What I've written is what I'm working with. – kaspnord Apr 02 '12 at 16:18
  • 1
    I'd rather you copy the code from the broken to here. What you post here should be *exactly* the entire file you ran. – ikegami Apr 02 '12 at 18:06
  • Since you keep looking at the same file, are you sure that's the file that is being executed? Have you tried `perl /path/to/whateveritis.pl`? Are you by accident executing something else instead? – Jonathan Leffler Apr 03 '12 at 03:09
  • @ikegami That is the exact code, less header that points to the Perl executable. – kaspnord Apr 03 '12 at 14:31
  • The solution to the problem was a little unexpected. I was running the code as `$ perl myfile.pl` in both machines. As you know, I got the GLOB when running it like so on one of my machines. However, using `$ ./myfile.pl` on that machine made the code run perfectly. Though I had specified Perl 5.8 in the directive, it was executing with 5.6 when I used `perl`. Using `./` made it execute with the 5.8 I specified in the directive. – kaspnord Apr 03 '12 at 14:51
  • I created a new file on the 'bad' machine with the exact same code, and it ran fine simply using `perl`. The original file was created on the 'good' machine, which I then copied over to the 'bad' machine. – kaspnord Apr 03 '12 at 14:53

4 Answers4

4

The broken file does not contain

my $report = <$fh>;    # aka: readline($fh)

Perhaps it contains

my $report = $fh;
my $report = < $fh >;  # aka: glob(" $fh ") = " GLOB(0xXXXXXXX) "
my $report = <$fh >;   # aka: glob("$fh ")  = "GLOB(0xXXXXXXX) "
my $report = < $fh>;   # aka: glob(" $fh")  = " GLOB(0xXXXXXXX)"

<> is a shortcut for readline or glob (no relation to the word GLOB in the output). The spaces make it become glob.

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • Sorry, I don't understand what you mean by my file possibly containing those variations of <$fh> - could you explain a little more? I didn't know variations of <$fh> even existed... – kaspnord Apr 02 '12 at 16:16
  • See the ["I/O Operators" section in perlop](http://search.cpan.org/perldoc?perlop#I/O_Operators) – mob Apr 02 '12 at 16:52
  • @kaspnord, I'm taking guesses as to what your file does contain, because it doesn't contain what you said it does. – ikegami Apr 02 '12 at 18:04
1

I would recommend just using the File::Slurp module from the CPAN. Then your code could look like this:

use File::Slurp 'read_file';
my $file = '/path/to/some/file';
my $report = read_file $file;
print("$report\n\n");

Much more readable and predictable, IMO.

Hercynium
  • 929
  • 9
  • 18
0

Yes, write

<$fh>

as $fh will lead to errors, as $fh is just the file handle. Printing it will be equivalent to printing the reference. Such as the below codes, writing as FH will leads to running time error.

open FH,$infile or die$!;
while(<FH>){
    @line=split(/,/);
    if($flag==0){
     foreach my $col (@line){
      $header{$col}=$count;
      $count++;
     }
 }
}
close(FH);
ikegami
  • 367,544
  • 15
  • 269
  • 518
Qiao Zhou
  • 149
  • 1
  • 4
0

One can use File::Slurp as Hercynium recommends, the mechanism that is closer to what the OP posted looks like:

my $report = do {
  open my $fh, '<', $file;
  local $/;
  <$fh>;
};

When done this way all of the changes are local to the do block, including closing the filehandle.

N.B. perldoc -f do tells us

do BLOCK

Not really a function. Returns the value of the last command in the sequence of commands indicated by BLOCK.

Note further than the context of the last executed statement is the context of the do block (here scalar). I find do blocks very useful (and under utilized); they are a great way to have lexical execution block, but still easily return something to the outer scope.

Joel Berger
  • 20,180
  • 5
  • 49
  • 104