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

I have this code. What I want to do is loop thru and append the file's content to array list? As I have it written now, @list is overriden. How do I append data to it?
foreach $DIR qw(TEST_DIR WINS_DIR) { if (defined($ENV{"$DIR"})) { $filename = $ENV{"$DIR"} . "/common/wins.ini"; if (-s $filename) { open (IN,$filename); chomp(@list=<IN>); close(IN); } } }

Replies are listed 'Best First'.
Re: Adding to array
by GrandFather (Saint) on Feb 28, 2007 at 20:29 UTC

    Read the new lines into a new list then push the new lines onto the end of the master list:

    use strict; use warnings; my @list; foreach my $DIR qw(TEST_DIR WINS_DIR) { if (defined($ENV{"$DIR"})) { my $filename = $ENV{"$DIR"} . "/common/wins.ini"; if (-s $filename) { open (IN,$filename); my @newList = <IN>; close (IN); chomp @newList; push @list, @newList; } } }

    Note too the use of strictures: use strict; use warnings;. All your code should use strictures!

    Update: You may find that using next cleans up the code by reducing nesting thus making it easier to see the important program flow:

    use strict; use warnings; my @list; foreach my $DIR qw(TEST_DIR WINS_DIR) { next unless defined($ENV{"$DIR"}); my $filename = $ENV{"$DIR"} . "/common/wins.ini"; next unless -s $filename; open (IN,$filename); my @newList = <IN>; close (IN); chomp @newList; push @list, @newList; }

    Oh, and you should use the three parameter open too. ;)

    open IN, '<', $filename;

    DWIM is Perl's answer to Gödel
      Thanks. The "next unless ..." is very good. BTW, I did use perl -w and use strict.

        Always declare variables in the smallest scope you can. There is a nasty trap implied by your code. Consider:

        use strict; use warnings; my $var = 'wibble'; foreach $var qw(foo bar) { print "$var\n"; } print $var;

        Prints:

        foo bar wibble

        Did you expect 'wibble' or 'bar' for that last value?

        The $var you declared outside the loop is not the $var used inside the loop. The loop variable is aliased to each value the loop iterates over. Using the form for my $var makes it clear to everyone that the scope of $var is just the loop and avoids the unfortunate assumption that the last value "assigned" to $var is available after the loop. Not a problem for your sample code, but a nasty trap waiting to bite you one day.


        DWIM is Perl's answer to Gödel
Re: Adding to array
by Fletch (Bishop) on Feb 28, 2007 at 20:24 UTC

    push onto it, don't assign to it.

Re: Adding to array
by mreece (Friar) on Feb 28, 2007 at 20:33 UTC
    using push:
    chomp(my @lines = <IN>); push @list, @lines;

    update: a complete different approach:

    get @ARGV to contain the list of files to slurp, then slurp it all with <>:

    @ARGV = grep { -s } map { defined $ENV{$_} ? "$ENV{$_}/common/wins.ini" : () } qw(TEST_DIR WINS_DIR); chomp(my @list = <>);
Re: Adding to array
by holli (Abbot) on Mar 01, 2007 at 08:31 UTC
    use File::Slurp; foreach $DIR qw(TEST_DIR WINS_DIR) { if (defined($ENV{"$DIR"})) { $filename = $ENV{"$DIR"} . "/common/wins.ini"; push @list, read_file( $filename ) if -s $filename; } }


    holli, /regexed monk/
Re: Adding to array
by wojtyk (Friar) on Feb 28, 2007 at 20:30 UTC
    foreach $DIR qw(TEST_DIR WINS_DIR) { if (defined($ENV{"$DIR"})) { $filename = $ENV{"$DIR"} . "/common/wins.ini"; if (-s $filename) { open (IN,$filename); push(@list,<IN>); chomp($list[$#list]); close(IN); } } }
      Both you and GrandFather follow the original code in calling chomp() on each partial list. Your solution only works if each file contributes only one line.

      Surely a single chomp() after the loop is simpler and more efficient.

      Anno

        In the context of file i/o the (most likely) very minor time difference between using chomp on the list for each file or once for the total list is completely irrelevant.

        As a style issue it seems sensible to have the chomp close to the place where the lines being chomped are generated so that it is clear why the chomp is there. It's a pretty minor issue however and the distance between the i/o and a single chomp would be small in this case any way.


        DWIM is Perl's answer to Gödel