Alister West

home is where your code is ...

Read a file with Perl

There are many ways to read a file in perl... this is my list.

Note: Bareword filehandles are global, so use localised ones to avoid namespace issues.


use File::Slurp qw/slurp/;
my @contents = slurp "foo.txt";
chomp @contents;

perlfunc open

open my $fh, '<', "foo.txt";

    # Then any of ..
    my @contents = <$fh>;  # lines
    my $contents = <$fh>;  # contents
    my @contents; while(<$fh>) { push @contents, $_; } # verbose
    read $fh, my $contents, -s $fh; # contents

close $fh;
chomp @contents;

Override @ARGV

By overriding @ARGV you can make perl handle opening and closing for you.
sub slurp { 
    local( $/, @ARGV ) = ( wantarray ? $/ : undef, @_ ); 
    return <ARGV>;   
my @contents = slurp( "foo.txt" );
chomp @contents;

# and the short 1-liner version for an existing fh
my $contents = do { undef local $/; <$fh> };

# 1 liner without a fh
my $contents = do { local ($/, @ARGV) = (undef, "foo.txt"); <ARGV> };


Commandline slurp and modify inplace for multi-line regex

# Note: not using -p as it won't match the first-line
perl -i.bak -e 'undef $/; $_ = <>; s/line1\nline2/new line/g; print' code.php

# Also use -0777 flag to set $/ to an impossible value (perldoc perlvar)
perl -0777 -p -i -e 's|<.DOCTYPE.*?<body>||msg' input.html


perl -i turns on inplace editing - but you can also do it in your script by setting $^I ($INPLACE_EDIT); And since its a script - not a oneliner - I (and you) should use variables.

local ($^I, @ARGV) = ('', '/tmp/foo_file.txt');
while (<>) {
By Alister West