Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re^2: Loop through array or filehandle

by markdibley (Sexton)
on Sep 29, 2016 at 16:07 UTC ( [id://1172938]=note: print w/replies, xml ) Need Help??


in reply to Re: Loop through array or filehandle
in thread Loop through array or filehandle

This is what I was getting at, but was wondering if there was a way of treating both sets of data within the same loop.

Is there any way of using the filehandle as an array (without loading the whole file into an array)?

Replies are listed 'Best First'.
Re^3: Loop through array or filehandle
by Laurent_R (Canon) on Sep 29, 2016 at 17:36 UTC
    I do not know if this is any better for your purpose, but you could create an iterator so that the loop uses the iterator and does not care where the data comes from (the iterator handles that part)

    Just a quick example:

    use warnings; use strict; open my $fh, '<', 'file.txt' or die $!; my @lines = ( "this is line 1; foo \n", "this is line 2: bar \n", "this is line 3: foobar \n", ); sub create_iter { my $arg = shift; if (ref $arg eq 'GLOB') { return sub {<$arg>}; } elsif (ref $arg eq 'ARRAY') { my $index = 0; return sub {$arg->[$index++]} } else { die "Unknown type\n"} } print "PRINTING FROM FH\n"; parse_line($fh); print "\n\nPRINTING FROM ARRAY\n"; parse_line(\@lines); sub parse_line { my $arg = shift; my $iter = create_iter($arg); while (my $val = $iter->()) { print $val if $val =~ /foo/; } }
    This prints out this:
    PRINTING FROM FH this is line 1; foo this is line 3: foobar this is line 4; foobaz PRINTING FROM ARRAY this is line 1; foo this is line 3: foobar

      Thanks again. I think you have come up with the simplest way to do this, although I modified the code slightly (below - doesn't run but is a simplified example of what I was doing). Originally I was wondering if there was a built-in technique that I was missing, but it appears not.

      Thanks again

      #!/usr/bin/perl -ws use strict; open my $fh, '<', 'file.txt' or die $!; my @lines = ( "this is line 1; foo \n", "this is line 2: bar \n", "this is line 3: foobar \n", ); print "PRINTING FROM FH\n"; working_routine($fh); print "\n\nPRINTING FROM ARRAY\n"; working_routine(\@lines); sub create_iter { my $arg = shift; if (ref $arg eq 'GLOB') { return <$arg>; } elsif (ref $arg eq 'ARRAY') { return shift @$arg; } else { die "Unknown type\n"} } sub working_routine{ my ($data) = @_; my $flag = 0; while(my $line = create_iter($data)){ if($line =~ /matches something/){ next; } elsif($line =~ /matches something else/ and ! $flag){ create_iter($data); my $newline = create_iter($data); dosomethingto($newline); } elsif($line =~ /gotcha/ && $flag){ morework($line); } else{ next; } } }
        The call to create_iter should not be in the while loop, create_iter should be called only once, to obtain the right iterator.

        What should go into the while condition is the call to the iterator returned by create_iter (i.e. $iter->() in my sample code).

      Interesting! Thanks. I get it.

      Interestingly, data from an HTTP::Request, when split by \n into an array, only loops to the first empty line and then the while loop stops. If the data from the request is written to a file then the while loop works as expected.

      The only work around I can find at the moment is to

      $data =~ s/^$/ /gsm

      Not ideal, but better than working out why an empty line from an HTTP::Request GET signals a termination of a while() loop.

        In Perl, an empty string is deemed to be false, therefore it will stop the while loop.

        The while loop should probably be amended to check for definedness rather than truth. I cannot test now on my mobile device, but will come back with a proposed solution as soon as I get a chance to test it.

        I.e.:

        my $iter = create_iter(...); ... while (defined(my $line = $iter->())) { do_something_with($line); }


        Give a man a fish:  <%-{-{-{-<

Re^3: Loop through array or filehandle
by Anonymous Monk on Sep 29, 2016 at 16:44 UTC
    Is there any way of using the filehandle as an array (without loading the whole file into an array)?

    Tie::File

      Thanks! Does what I wanted (although originally I was looking to see if there was some clever way of using filehandles built into the perl core - should have explained that better).

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1172938]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (5)
As of 2024-04-23 21:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found