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

Hi, I have many files in this format:
line 1
line 2
line 3
..
line 12
I need to read them into an array, which should look like this:
line1 line2 line3 .. line 12 # content of file 1 
line1 line2 line3 .. line 12 # content of file 2 .. 
line1 line2 line3 .. line 12 # content of file x 
I've started with the following code:
foreach $member (@memberlist) { open(FILE, "$member.dat"); lock(FILE); @members = <FILE>; unlock(FILE); close(FILE); foreach $line (@members) { push(@allmembers, $line); } }
But this of course prints only all lines under each other. Can anybody tell me how to go on?

Thank you in advance for help
Karl

Replies are listed 'Best First'.
Re (tilly) 1: Reading content of many files in an array
by tilly (Archbishop) on Sep 25, 2001 at 04:14 UTC
    I am moderately appalled at the answers in this thread. So far nobody has pointed out that you should do as perlstyle says and put an error check on your open statement, and several people gave you answers with the mistake repeated. I really think that we as posters should be setting good examples here.

    Secondly your loop variable is not declared with my. That is an excellent sign that you have not yet been introduced to strict.pm, which is another habit to point out since it will save you a lot of grief and debugging time in the future.

    Thirdly you are not localizing your filehandle. Given that you are naming it something fairly generic, this habit may come back to haunt you in the future even though it is not bothering you now.

    Fourth you don't show us what your lock function looks like. But if it is based on OS-level locks (eg flock) then as merlyn points out at Don't use unflock (flock 8). Ever., there is no need to unlock if you are about to close. In fact it is a good thing to be in the habit of not doing.

    Fifth, you don't show us what your lock function looks like, but it is very important for it to have an error check. There are many configuration issues that can cause locking to stop working, and it is very hard to notice that before it hits production. This is a much more important detail than the error check on the open.

    And finally, my experience suggests strongly that locking file access is the wrong thing to do. You want to lock entire logical operations, and what constitutes a logical operation is something that depends on your application. When people try to lock at a file operation level, their overall code tends to wind up with race conditions. Since most people have a very hard time seeing race conditions, this tends to lead to periodic and hard to track down bugs. See the thread starting at RE: Flock Subroutine for more on this.

    Now I don't expect the average PerlMonk to come up with all of the items on this list. But I am disappointed that apparently nobody noticed any of them. :-(

Re: Reading content of many files in an array (join)
by mandog (Curate) on Sep 25, 2001 at 02:31 UTC
    for details see: perldoc -f join
    @members = <FILE>; $line =join(' ', @members);
    Hope this helps

    --mandog
Re: Reading content of many files in an array
by jlongino (Parson) on Sep 25, 2001 at 02:38 UTC
    Will this do what you want?
    my (@memberlist, @allmembers); foreach my $member (@memberlist) { open(FILE, "$member.dat") or die "Open failed for file: '$member.dat'. $!\n"; lock(FILE); my @members = <FILE>; unlock(FILE); close(FILE); chomp @members; push (@allmembers, join (" ", @members)); }
    Update: tilly is absolutely right! We should know better.

    "Make everything as simple as possible, but not simpler." -- Albert Einstein

Re: Reading content of many files in an array
by Zaxo (Archbishop) on Sep 25, 2001 at 02:39 UTC

    You can remove the newlines with chomp, then join to make a single line:

    foreach $member (@memberlist) { open(FILE, "$member.dat") or die $!; lock(FILE); @members = <FILE>; chomp(@members); push @allmembers, join( " ", @members); unlock(FILE); close(FILE) or die $!; # remove this # foreach $line (@members) { # push(@allmembers, $line); # } }

    Update: Fixed a blunder, props to wog.

    Update2: Should have also corrected your open and close, props to tilly.

    After Compline,
    Zaxo

Re: Reading content of many files in an array
by blakem (Monsignor) on Sep 25, 2001 at 02:39 UTC
    Instead of pushing each $line onto @allmembers as its own element, you could chomp the @members array then join the contents of @members into a string. Pushing this string onto @allmembers should then be what you want...
    foreach my $member ( .... ) { .... close(FILE); chomp @members; my $bigline = join(' ',@members); push(@allmembers,$bigline); .... } for my $longline (@allmembers) { print "$longline\n"; }
    Update added my to original foreach loop var per tilly's wise words.

    -Blake

Re: Reading content of many files in an array
by ducky (Scribe) on Sep 25, 2001 at 02:53 UTC

    How about this?

    Offending code removed
    Clearing the record separator ($/) makes it take the entire contents of the file on read, this also preserves the new line chars, though, too.

    HTH

    Update:tilly's right on the mark: an answer using proper code takes precidence over minimally changing the presented code to work. So, this is my final answer, ie., how I would've done this from scratch:

    my @member_list = qw( fileone filetwo filethree ) ; my @all_members = () ; for my $file ( @member_list ) { open IN, "$file.dat" or die "Can't open '$file': $!" ; local $/ ; push @all_members, <IN> ; close IN ; }

    -Ducky