Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Loop through array or filehandle

by markdibley (Sexton)
on Sep 29, 2016 at 13:57 UTC ( [id://1172929]=perlquestion: print w/replies, xml ) Need Help??

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

Hello

I have a subroutine that loops through some data in a file until it has found the correct outcome and then stops. I simply pass a filehandle reference to the subroutine to do it.

However, I now have a new source of data that gives it to me in a smaller string. To apply the some routine I just need to split the data by \n and could pass the array reference to the subroutine.

But is there a way to write a subroutine that takes either a filehandle ref or array ref to loop through?

I am looking for a way that does not involve reading the whole file into a string (although I admit this may because I am old and started programming computers that had never heard of GB memory).

Is it possible?

Replies are listed 'Best First'.
Re: Loop through array or filehandle
by RichardK (Parson) on Sep 29, 2016 at 14:13 UTC

    You can open a file handle on the string directly, see open

    for example :-

    use v5.22; use warnings; use autodie; my $mydata = "this\nthat\n"; open (my $fh, '<' , \$mydata); while (<$fh>) { print $_; }
Re: Loop through array or filehandle
by Athanasius (Archbishop) on Sep 29, 2016 at 14:12 UTC

    Hello markdibley,

    Have a look at the documentation for PerlIO::scalar:

    A filehandle is opened but the file operations are performed "in-memory" on a scalar variable. All the normal file operations can be performed on the handle. The scalar is considered a stream of bytes.

    This will allow you to use your current subroutine as-is: just pass it a “filehandle” opened to point to the variable containing the string.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Loop through array or filehandle
by stevieb (Canon) on Sep 29, 2016 at 14:14 UTC

    So if I understand correctly, the data in the new format will all reside in one array, with a single line per element. If so, have a review of this example code. I simply check the reference type with ref, and act accordingly.

    My test input file (file.txt) contains:

    this is line 1 in fh blah this is line 2 in fh

    Code:

    use warnings; use strict; my $search = 'blah'; open my $fh, '<', 'file.txt' or die $!; my @lines = ( "this is line 1 of aref\n", "this is line 2 of aref blah\n", ); parse_line($fh); parse_line(\@lines); sub parse_line { my $arg = shift; if (ref $arg eq 'GLOB'){ # file handle while (<$arg>){ if (/$search/){ print; last; } } } elsif (ref $arg eq 'ARRAY'){ # aref for (@$arg){ if (/$search/){ print "$_\n"; last; } } } else { print "unsupported type...\n"; exit; } }

    Output:

    this is line 1 in fh blah this is line 2 of aref blah

      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)?

        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
        Is there any way of using the filehandle as an array (without loading the whole file into an array)?

        Tie::File

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1172929]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (4)
As of 2024-03-29 08:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found