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

How do you read a whole line from first file which merges with first character of second file and third file.And similarly second line of first file with second character of second and third file...and so on. Thankx for your help.

Replies are listed 'Best First'.
(jeffa) Re: Reading arrays
by jeffa (Bishop) on Jul 31, 2000 at 20:21 UTC
    Well, this should do the trick. I did not do any bounds error checking on the arrays that hold the files. This will just give you an idea how to solve the problem:
    use strict; my (@lines1, @lines2, @lines3); &load_array(\@lines1, "foo1.dat"); &load_array(\@lines2, "foo2.dat"); &load_array(\@lines3, "foo3.dat"); for (my $i = 0; $i < @lines1; $i++) { my ($word2) = split(/ /, $lines2[$i]); my ($word3) = split(/ /, $lines3[$i]); print "$lines1[$i]:$word2:$word3\n"; } sub load_array($$) { my ($a_ref, $file) = @_; open (FILE, $file) or die "Can't open $file:$!\n"; @{$a_ref} = <FILE>; close FILE; chomp @{$a_ref}; }
    As you can see, this will bomb if the first file contains more lines than the other two files - recursive turnary operator, anyone? There is lots of improving that can be done to this rather unelegant piece of code . . . but this does the trick - hope this helps.
      Thankx.I wanted to get certain lines rather than all lines. What should I use rather than for loop?
        Just change the entire for loop to this:
        foreach (qw(0 3 8 20)) { my ($word2) = split(/ /, $lines2[$_]); my ($word3) = split(/ /, $lines3[$_]); print "$lines1[$_]:$word2:$word3\n"; }
        Just substitute the desired line numbers (each one -1, remember) inside qw(). If you do have large data files, use gryng's method below.

        To grying: sorry for making you gag, I am studying your method closely to make up for it.

Somewhat general solution
by gryng (Hermit) on Aug 01, 2000 at 00:57 UTC
    #!/usr/bin/perl -w use strict; use IO::File; my $verbose = 1; my @fh; while (my $name = shift @ARGV) { my $file = new IO::File; print "Opening $name\n" if $verbose; open ($file,$name); push @fh, $file; } my $n = 0; READ: while (++$n) { my @filelines; for my $file (@fh) { my $line = <$file> || last READ; push @filelines, $line; } # Now @filelines contains the nth line from each file # so do whatever printing you want with it. I'm going # to print out the first word on each line: print "$n = " if $verbose; print +(join " : ", map {chomp;(split /\s+/, $_, 2)[0]} @filelines), +"\n"; }
    This will read whatever files you specify on the command line, and then print the first word on each line. All you need to do is change the printing lines to print what it is you actually want -- the array @filelines contains the nth line from each file. (Sorry the other solution I saw made me gag at the memory usage on large files :) -- I'm still a stickler for that).

    Also, you can use the $n variable and whatever if statements to just not print that line if you don't want it.

    Ciao,
    Gryn

Re: Reading arrays
by merlyn (Sage) on Jul 31, 2000 at 18:28 UTC
    Other than the readline (angle-bracket-around-a-filehandle) operator, and substr and string concatenation and variables, are you looking for some strange undocumented magic?

    -- Randal L. Schwartz, Perl hacker

      I am completely new in perl. Are you the same Randal L. Acwartz who wrote 'learning perl'. As a matter of fact I am using your book to learn perl.
        Sorry!...Typo!
        Are you the same Randal L. Acwartz who wrote 'learning perl'.
        Well, my mom spells it "Randal L. Schwartz", but other than that, yes. {grin}

        -- Randal L. Schwartz, Perl hacker