in reply to Open Function Question

"< $i" results in a string similar to "< SCALAR(0x814f66c)" because references can't exist in a string (by definition). open my $myfile, "< $i" doesn't find a file named SCALAR(0x814f66c), so it returns an error.

Since 5.8, when you use the three arg form of open and the third arg is a scalar reference, the referenced scalar is used as a virtual file from which data can be read or to which data can be written.

Replies are listed 'Best First'.
Re^2: Open Function Question
by bichonfrise74 (Vicar) on Apr 17, 2009 at 19:57 UTC
    If it is a scalar, then shouldn't the line below work? I guess in this situation, how do you open the heredoc using the 2 arguments of "open"?
    open my $myfile, "< $$i" or die "cannot open file";
      I think you are getting more confused. You don't "open" a heredoc. $$i will contain the string "abc\n", so open will attempt to open a file with that name. A newline may or may not be a valid character for a file name, so you may or may not be able to even create a file with such a name to read from. Once you put quotes around a variable, it stringifies it, so the value returned from the quote operator is no longer a reference, it's a string, which is why $i didn't work as you expected either.

      Before going on, I'd like to know if you realize that

      my $file1 = <<END_FILE2; abc END_FILE2

      is just another way of writing

      my $file1 = "abc\n";

      how do you open the heredoc using the 2 arguments of "open"?

      Neither know anything about heredocs. Your request to open a heredoc is nonsense.

      As for the ability to create file handles that read from or write to a scalar, the 2-arg version can't do that.

      If $i is some string, like: $i = 'abc/def', then,
      open (my $myfile, "$i") or die... open (my $myfile, "<$i")or die... #no space after < open (my $myfile, '<', "$i") or die... take your pick...
      open (my $myfile, '<', \$i) or die...

      UPDATE:

      open (my $myfile, "$i") or die... open (my $myfile, $i) or die... open (my $myfile, "<$i")or die... #no space after < required open (my $myfile, "< $i")or die... open (my $myfile, '<', "$i") or die... open (my $myfile, '<', $i) or die... \$i is wrong above....

        If $i is some string, like: $i = 'abc/def', then,

        open (my $myfile, "$i") or die... open (my $myfile, "<$i")or die... #no space after < open (my $myfile, '<', "$i") or die... open (my $myfile, '<', \$i) or die... take your pick...

        A few points:-

        • The double-quotes around $i are un-necessary in your first line of code.
        • A space after the '<' is allowable in your second example.
        • Your fourth example is going to do something quite different to the other three.

        Given this file ...

        $ cat abc/abc.txt line 1 line 2 $

        ... and this script ...

        use strict; use warnings; my $fn = q{abc/abc.txt}; print qq{\nTest 1:\n}; print do{ open my $fh, $fn or die qq{open: Test 1: \n}; <$fh>; }; print qq{\nTest 2:\n}; print do{ open my $fh, qq{<$fn} or die qq{open: Test 2: \n}; <$fh>; }; print qq{\nTest 3:\n}; print do{ open my $fh, qq{< $fn} or die qq{open: Test 3: \n}; <$fh>; }; print qq{\nTest 4:\n}; print do{ open my $fh, q{<}, $fn or die qq{open: Test 4: \n}; <$fh>; }; print qq{\nTest 5:\n}; print do{ open my $fh, q{<}, \$fn or die qq{open: Test 5: \n}; <$fh>; }; print qq{\n};

        ... the following output is produced.

        Test 1: line 1 line 2 Test 2: line 1 line 2 Test 3: line 1 line 2 Test 4: line 1 line 2 Test 5: abc/abc.txt

        Note that "Test 2" and "Test 3" work in exactly the same way. Note also that in "Test 5", which is analogous to your fourth code line, the filehandle actually reads the text contained in the scalar, as demonstrated in BrowserUk's response, rather than the file contents.

        I hope this is of interest.

        Cheers,

        JohnGG