Home > Enterprise >  Perl: Filehandle storing the full file content and not each line
Perl: Filehandle storing the full file content and not each line

Time:12-28

Content of file "/serrs/env.txt" is :

abc
def
ghi jkl mno
good is the conet

Code Snippet is :

    use strict;
    use warnings;
    
    my $ModeRefFile;
    open(FH2, '<', "/home/vivi/ee/ppp.pl") or die $!;   
    local $/ = undef;
    $ModeRefFile = <FH2>;
    close(FH2);
    
    open(FH3, '<', "/serrs/env.txt") or die $!;
    while (<FH3>)   {
         chomp ($_);
         print "$_ is the line which is being read\n";
    }
    close(FH3);
       

Output:

abc
def
ghi jkl mno
good is the conet is the line which is being read

What I want (expected):

abc is the line which is being read
def is the line which is being read
ghi jkl mno is the line which is being read
good is the conet is the line which is being read

Why is $_ in the second open (open(FH3, '<', "/serrs/env.txt") storing the whole content of a file even though output record operator is changed in the first open (open(FH2, '<', "/home/vivi/ee/ppp.pl")), and that too using "local". As per my understanding, $_ in the second open ( open(FH3, '<', "/serrs/env.txt") shall contain each line. How can i achieve it?

CodePudding user response:

local $/ or local $/ = undef, or $/ = undef are all different ways to do the same thing, which is to disable the record input separator. If you use local in the top block of a file (or same block), it has no effect, but will be global throughout the file. The local is also a way to override the already existing variable, meaning "this is a local version of the variable".

The idiomatic way to use local $/ is this:

my $filecontent = do { 
             open my $fh, '<', "foo.bar" or die $!; 
             local $/;       # local version of $/, now undef
             <$fh>;          # return the whole file in one string
};

This way, local $/ stays lexically scoped where you need it, and does not effect the rest of the code.

Also, this way your file handle is lexically scoped and is closed when the block ends.

Another interesting side effect of your code is that chomp now removes nothing, as it is controlled by the content of $/.

CodePudding user response:

The documentation for local() says this:

A local modifies the listed variables to be local to the enclosing block, file, or eval.

It's the "enclosing block" that's important here. There is no enclosing block around your call to local() so it is in force for the rest of the program - including when you are processing FH3.

Instead of:

local $/ = undef;
$ModeRefFile = <FH2>;

Try this:

$ModeRefFile = do { local $/; <FH2> };

That way, the local() only has effect inside the block of code.

  • Related