Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

Re: Reading two text files parallelly...

by Hugmeir (Sexton)
on Nov 08, 2010 at 19:56 UTC ( #870182=note: print w/replies, xml ) Need Help??

in reply to Reading two text files parallelly...

For starters, strictures and warnings.. Also, you are opening the files for writing, but using them for reading.

open my $fh1, "<", $file1 or die "Cannot open file $file1: $!"; open my $fh1, "<", $file2 or die "Cannot open file $file2: $!";

Then, with while ( <F1>, <F2> ), you'd be reading a line from each file, not assinging it to anything, and entering the loop; $_ is only set while using while (<$file>). (I think.)

Really, that's quite a bad post you have there. Still, I've never tried something like this, so have a freebie from another newbie (and please try to ignore the awful variable names..):

use strict; use warnings; use 5.010; use autodie; open my $fh1, '<', 'file1'; open my $fh2, '<', 'file2'; while (my $test1 = <$fh1>, my $test2 = <$fh2>) { chomp($test1 //= ''); chomp($test2 //= ''); say "$test1, $test2"; }

Replies are listed 'Best First'.
Re^2: Reading two text files parallelly...
by Marshall (Abbot) on Nov 09, 2010 at 17:16 UTC
    while (my $test1 = <$fh1>, my $test2 = <$fh2>) This is "comma operator". The "true" or "false" of the "while" only depends upon the state of $test2. The comma operator is a way to combine two what normally would be completely separate statements "together". This should be used only with extreme caution.

    A common use for this is in user prompting loops. Putting the prompt together with the ending condition solves the problem of "how to get the loop started" and at the same time puts the condition that is going to stop the loop right up there where it belongs - right in the statement that runs the loop - not buried somewhere in the "guts".

    Here is an example. We are asking about part numbers. The user prompt is clear. What stops the loop is clear (q,Q,QuIT, etc) and it is right there where it is supposed to be, in the controlling loop statement. In the "guts" of the loop there will be many error messages like "hey, dummy a part number needs 10 digits" or whatever, followed by a "next;" statement - that restarts the loop and re-prompts the user.

    while ( (print "Enter Part No and Qty: "), (my $line=<STDIN>) !~ /^\s*q(uit)?\s*$/i ) {...}
    Some would argue that it is better to move the ending condition into the loop and make it the first statement. Well ok thats one way. In that case we have:
    last if $line !~/^\s*q(uit)?\s*$/i;
    I would argue against that as "do forever" loops should be reserved for servers, GUI event loops and such.

    In any event, the OP doesn't appear to be in need of such things.

      This is "comma operator". The "true" or "false" of the "while" only depends upon the state of $test2.

      Oh, completely missed that.. All my tests had the second file longer than the first. ++ for the explanation! If I may take another moment of your time, I tried fixing that code from before, although now I think that I'm using one of those endless loops you adviced against:

      while (my ($test1, $test2) = (scalar <$fh1>, scalar <$fh2>)) { last unless defined $test1 or defined $test2; ... }
      I figure that the simplest fixes (for me, that is: Feel free to kick me on the right path) would be to either use the defined-or on the results of the readlines, replacing the undefs with the empty list, or move everything into a sub.

      ..actually, rather than talk about it:


      while ( my $test1, $test2 ) = (scalar <$fh1> // (), scalar <$fh2> // ( +) ) { ... }
      sub read_double_file { my ($fh1, $fh2) = @_; my ($line_file_1, $line_file_2) = (scalar <$fh1>, scalar <$fh2>); (defined $line_file_1 or defined $line_file_2) ? ($line_file_1 //= +'', $line_file_2 //= '') : (); } while ( my ($line_from_1, $line_from_2) = read_double_file($fh1, $fh2) + ) { ... }
      Is there a better approach? (For whatever reason, trying to solve this has been quite fun -- I'm even thinking about meddling with objects, just so I don't have to pass the filehandles over and over to the subs) Are the attempts so far horribly, terribly wrong?
        Sounds like the main problem is to get very clear about what you want this program to do. If you want to just stop when both files are over, or when lines run out of one of them, another possibility is below. The while() takes an expression that evaluates to true/false. Nothing wrong with have more than one condition in an "and" statement. You can use "or" if you want. I don't see the need for anything fancy - try to keep it as easy to understand as possible.
        #!/usr/bin/perl -w use strict; open (my $fh1, '<', "testa.txt") or die "cannot open testa"; open (my $fh2, '<', "testb.txt") or die "cannot open testb"; while ( defined (my $test1 = <$fh1>) and defined (my $test2 = <$fh2>) ) { print "both defined\n"; }

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://870182]
[marto]: trench humour folks, feeling rough.
[marto]: there is never a night when they sleep all the way through, but last night was something else
[marto]: gave in at 3:45 ish and let Charlie watch videos about spitfires, the battle of Britain. He's plane crazy
[1nickt]: marto soothing!
[marto]: Hiromi makes an appearance, let's hope Jools doesn't ruin it by joining in on the old Joanna
[1nickt]: karlgoethebier What is the issue with the semic-colon after the ellipsis? It's documented as proper syntax ...;
[karlgoethebier]: Crazy? What should i say? Son just started his third studies. Next week i have a session with my therapist ;-)
[marto]: and just as I type that, the boys begin playing the piano, the price I pay for using cockney slang :P

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (6)
As of 2017-11-18 18:56 GMT
Find Nodes?
    Voting Booth?
    In order to be able to say "I know Perl", you must have:

    Results (277 votes). Check out past polls.