http://www.perlmonks.org?node_id=981144

maheshkumar has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to put each line of a text file in an array, but encountering some problem with the logic. Can any one tell if the following logic is correct?

use warnings; @ARGV = 'Google_1'; my @results; while ( <ARGV> ){ chomp $_; if($_ =~m/head/){ push (@results, $_); } } print "@results\n";

or can we use hash with these? My text file looks something like this but it has around 40k lines

192.168.178.1 82.135.16.28 212.18.7.101 212.18.6.166 80.81.192.28 92.123.72.112 82.135.16.28 212.18.7.101 212.18.6.77 217.71.108.93 217.71.96.169 194.59.190.3 134.222.231.49 134.222.229.49 134.222.229.205 134.222.229.222 134.222.231.22 62.41.85.112

Replies are listed 'Best First'.
Re: Putting files in an Array
by toolic (Bishop) on Jul 11, 2012 at 15:18 UTC
    but encountering some problem with the logic
    Can you specify what problem you are having?

    Since none of the lines of your text file have the string "head", you are not pushing any of those lines into your array. Try this:

    use warnings; use strict; @ARGV = 'Google_1'; my @results; while (<ARGV>) { chomp $_; push( @results, $_ ); } print "@results\n";
Re: Putting files in an Array
by blue_cowdawg (Monsignor) on Jul 11, 2012 at 15:20 UTC

    Personally for treating a file like an array I am a fan of using Tie::File

    From the CPAN site:

    # This file documents Tie::File version 0.98 use Tie::File; tie @array, 'Tie::File', filename or die ...; $array[13] = 'blah'; # line 13 of the file is now 'blah' print $array[42]; # display line 42 of the file $n_recs = @array; # how many records are in the file? $#array -= 2; # chop two records off the end for (@array) { s/PERL/Perl/g; # Replace PERL with Perl everywhere i +n the file } # These are just like regular push, pop, unshift, shift, and s +plice # Except that they modify the file in the way you would expect push @array, new recs...; my $r1 = pop @array; unshift @array, new recs...; my $r2 = shift @array; @old_recs = splice @array, 3, 7, new recs...; untie @array; # all finished

    Essentially anything you do with an array you can do with a file.


    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
Re: Putting files in an Array
by kcott (Archbishop) on Jul 11, 2012 at 15:39 UTC

    Your problem here seems to be that you're only pushing lines onto the array if they match /head/ but none of your sample lines match this. Result: empty array. Perhaps you meant !~ instead of =~.

    It's difficult offering concrete advice here as your written explanantion "... put each line of a text file in an array ..." contradicts your code which is conditionally adding lines to the array. Furthermore, you'd probably get a better answer if we knew what you were planning to do with this array beyond print "@results\n";.

    Maybe take a look at Tie::File. This will read all lines into an array in a single statement. The size of your file is not an issue with this module.

    -- Ken

Re: Putting files in an Array
by cheekuperl (Monk) on Jul 11, 2012 at 15:17 UTC
    I am trying to put each line of a text file in an array
    All you need is this (after opening the file):
    @lines=<FILEHANDLE> #slurp it
    But I see your code conditionally pushes elements into array. Nothing seems wrong with the code. Two things:
    1) Open file statement is missing.
    2) Instead of using $_ everywhere, use your own variable.
      It looks like there's no need to open the file here, because the filename is in the @ARGV. It is as if it comes from STDIN. In this case this works @lines=<>;
Re: Putting files in an Array
by jethro (Monsignor) on Jul 11, 2012 at 15:26 UTC

    ARGV in the while condition needs a '@'. Did you ever try to execute the script? UPDATE: Please ignore this line, I must have been in auto-destruct mode ;-). Thanks monsoon for the speedy correction

    Naturally you could use a hash as well. Whether it works better with a hash or an array depends on what you need to do with the data. It also depends on the data. Since you only put lines into @results if they have "head" somewhere in the line and your example text file has not one line with "head" in it, an empty hash is as good as an empty array ;-)

    PS: Your script seems to be a copy of a script suggested to you in this thread Out of Memory in Perl. I hope Zentara forgives me for saying this, but his advice to use @ARGVs magic just to read a file line by line is misleading. First of all it won't work to save memory by reading a file line by line if you then store it into an array anyway. And secondly you can read a file line by line without using @ARGV magic

    Your original script (with the bug corrected) would have done the job as well.

      <@ARGV> won't work. ARGV is a special filehandle. See here
      First of all it won't work to save memory by reading a file line by line if you then store it into an array anyway.

      Sorry if I was misleading. In the original post, IIRC, he complained about filtering 2 gig files. The ARGV trick pushed matches into a @results array, and unless he had 2 gig's worth of matches, he should not run out of memory. In this node, he seems to want to slurp all lines into the array. I think that caused confusion, because in this node he wanted to use the ARGV trick on small files.


      I'm not really a human, but I play one on earth.
      Old Perl Programmer Haiku ................... flash japh
Re: Putting files in an Array
by zentara (Archbishop) on Jul 11, 2012 at 18:02 UTC
    Sorry I mislead you with the line if($_ =~m/head/){}

    It was just meant as an example regex. If you want to see how it works, with your test file try

    if($_ =~m/134/){ }
    As others have pointed out, just to slurp a small file into an array, there are better ways than using <ARGV>. Your usage is Ok, but for small files you really don't need that type of code, as it was designed for line-by-line processing of huge files.

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
Re: Putting files in an Array
by Kenosis (Priest) on Jul 11, 2012 at 15:48 UTC

    My text file looks something like this... (only IP addresses shown)

    Perhaps I'm missing something, but you push a line onto an array if($_ =~m/head/), but there's no such match in the lines you've shown, so none of those IPs would end up in the array. Were you, in fact, only interested in those lines with "head" in them?

    Update: Ken was much faster at this observation...