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

I wish to create a script that reads from n files until i have m total unique lines. In order to do this, I would like to use anonymous file handles. my code just gives me warnings which suggest that lines are not being read. can anyone give me a pointer as to what is wrong with my code?
#!/usr/bin/perl use strict; use warnings; my $wantedLines = shift; # number of unique instances wanted my $numFiles = 0; my @files = (); while( my $file = shift) { open $files[$numFiles++], '<', $file or die "can't open $file, $!\ +n"; } my $totalLines = 0; my $ct = 0; my %unique = (); while($totalLines <= $wantedLines) { my $num = $ct++; $num = $num%$numFiles; print "$num\n"; my $this = <$files[$num]>; unless(exists $unique{$this}) { print $this; $totalLines++; } }
  • Comment on reading from an arbitrary number of files using anonymous file handles
  • Download Code

Replies are listed 'Best First'.
Re: reading from an arbitrary number of files using anonymous file handles
by JadeNB (Chaplain) on Dec 05, 2008 at 23:21 UTC
    The cheap answer (cheap because there should be a better one, but I don't know it) is that <$handle> seems to work, but <$array_of_handles[0]> doesn't. Changing
    my $this = <$files[$num]>;
    to
    my $handle = $files[$num]; my $this = <$handle>;
    should work.

    By the way, you read one line too many. Your while test should be $totalLines < $wantedLines.

    UPDATE: Thanks to Tanktalus for pointing me to the documentation. I/O Operators has this to say:

    As the documentation suggests, and almut and Perlbotics point out below, readline will probably serve better.

Re: reading from an arbitrary number of files using anonymous file handles
by almut (Canon) on Dec 05, 2008 at 23:30 UTC

    ...as JadeNB said.  Or use readline:

    my $line = readline $files[$num];
Re: reading from an arbitrary number of files using anonymous file handles
by Perlbotics (Archbishop) on Dec 05, 2008 at 23:40 UTC

    You can use readline instead of the <angle brackets>

    ... # my $this = <$files[$num]>; my $this = readline($files[$num]); ...
    In order to take track of unique lines, you might want to complement:
    unless( ... ) { ... $unique{$this}++; ... }

Re: reading from an arbitrary number of files using anonymous file handles
by Not_a_Number (Prior) on Dec 06, 2008 at 00:11 UTC

    Just for fun(?):

    use strict; use warnings; my $wantedLines = shift; my %seen; while ( <> ) { print unless $seen{$_}++; last unless --$wantedLines; }

    Update: Sorry, I posted the wrong version. Replace the contents of the while loop with:

    unless ( $seen{$_}++ ) { print; last unless --$wantedLines; }
Re: reading from an arbitrary number of files using anonymous file handles
by eye (Chaplain) on Dec 06, 2008 at 07:11 UTC
    Although not part of the OP's question, I think it is a bad idea to open all the files in advance of reading from any. This makes the code more fragile than it needs to be.