Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

How to collect the stdout of a subroutine call?

by Anonymous Monk
on Apr 19, 2004 at 18:07 UTC ( [id://346375]=perlquestion: print w/replies, xml ) Need Help??

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

Hi, How can I capture the results of a subroutine in perl to a scalar variable?
Like:
If my subroutine results are:

Name:xxx
Address: Main street
City: Boston
Phone: 123 234 2345

Can I do this:
If my sub is called &results.
I call it on my program like
&results;
But can I get the results of it into a scalar?
$variable = &results();
Is it possible?
Thanks!
  • Comment on How to collect the stdout of a subroutine call?

Replies are listed 'Best First'.
Re: How to collect the stdout of a subroutine call?
by b10m (Vicar) on Apr 19, 2004 at 18:12 UTC

    Make sure you return the value in your sub routine. Something like:

    my $variable = results(); sub results { # ... do something that will give $foo the stuff you want # to return ... return $foo; }
    --
    b10m

    All code is usually tested, but rarely trusted.
Re: How to collect the stdout of a subroutine call?
by fletcher_the_dog (Friar) on Apr 19, 2004 at 18:14 UTC
    I would suggest trying your idea and seeing if it works.
    sub results { return "Name:xxx Address: Main street City: Boston Phone: 123 234 2345" } $variable = &results(); print $variable;
      Here is the code but it still doesn't work.
      my $xx = &log; print "<b>$xx</x>";

      Don't know why???
      sub log { my $log_file = "log.txt"; open(LOGFILE, "$log") or die("Could not open log file."); #my %seen; my %seen = (); my %typeseen = (); # read it in my $test = "Home Company"; while(<LOGFILE>) { next unless /($test)\*(.*?)\*(.*?)\*(.*?)\*(.*?)\*(.*?)\*(.*?)\*(. +*?)$/; my ($item, $logintype) = ($1, $4); #print $item; $seen{$item}++; $typeseen{$item}{$logintype}++; } # dump it out foreach my $item (sort keys %seen) { print "$item:<br>\n"; print "\tLog in activity: ", $seen{$item}, "<br>\n"; foreach my $type (sort keys %{$typeseen{$item}}) { print "\t", $type, " activity: ", $typeseen{$item}{$type}, "<br>\n +"; } } } ####### END SUB LOG
        Your subroutine prints out information, rather than returning it. If you want to capture what is printed into a variable, you would need to have it run as a separate process (see fork) so that you can read its STDOUT. (Or, the easier way, just have it build up a string and return that, as so many others have suggested.)

        The PerlMonk tr/// Advocate
        If you don't want to change the code in the subroutine to accumulate and return a string, instead of printing, you can try the following. Similar but prettier techniques use non-standard modules.
        # somewhere near the top of your code, put this: { package AccumHandle; sub TIEHANDLE { my( $pkg, $s ) = shift; bless \$s, $pkg } sub PRINT { my $self = shift; $$self .= join($,,@_).$\; } } # now do this where you call the subroutine: local ACC; tie *ACC, 'AccumHandle'; select ACC; &log(); select STDOUT; my $xx = ${tied(*ACC)}; print "<b>$xx</x>";
        Btw - this question is a (currently unapproved) Categorized Question: How can I write a function's output to a scalar?.

        jdporter
        The 6th Rule of Perl Club is -- There is no Rule #6.

        You must use the return statement inside your subroutine. I am not sure I understand exactly what you are trying to do from reading your code, but I am assuming you want everything you are printing to be returned (Update and not printed). In that case you need to put the data in the variable first, then return it. Like this.... (code not tested)

        my $output; foreach my $item (sort keys %seen) { $output .= "$item:<br>\n"; $output .= "\tLog in activity: ", $seen{$item}, "<br>\n"; foreach my $type (sort keys %{$typeseen{$item}}) { $output .= "\t", $type, " activity: ", $typeseen{$item}{$type}, "< +br>\n"; } return $output; }

        log is a builtin function (logarithm) so it is not a wise idea to define a new function with the same name. While it might not be the problem in this case, you should avoid this in the future not to fall in the trap. (I once tried to define a log function in C.)

Re: How to collect the stdout of a subroutine call?
by disciple (Pilgrim) on Apr 19, 2004 at 18:35 UTC
    If you want to return the values into individual variables....
    ($name, $address, $city, $phone) = &getInfo(); print "Name: $name\nAddress: $address\nCity: $city\nPhone: $phone"; sub getInfo(){ return ("xxx", "Main street", "Boston", "123 234 2345"); }
Re: How to collect the stdout of a subroutine call?
by Aragorn (Curate) on Apr 19, 2004 at 18:50 UTC
    You can return the results as a string, but (and I'm guessing here) I think it would be more useful if the results are returned as a hash reference:
    sub results { # Guessing that the results are in separate variables $name, # $address, $city, $phone: return { name => $name, address => $address, city => $city, phone => $phone, }; }
    Now you can get to the separate entries of the results in your main program:
    my $info = results(); print "Name: " . $info->{name} . "\n"; # And of course $info->{address}, $info->{city} and $info->{phone}
    Take a look at perldsc and perlref for more information on how these things work.

    Arjen

Re: How to collect the stdout of a subroutine call?
by ysth (Canon) on Apr 19, 2004 at 22:47 UTC
    With perl5.8 and above, you can easily capture what the subroutine prints like:
    # create a variable to store the output in my $output = ""; # open a "file" that will store output in the variable # (requires 5.8; before that use CPAN module IO::Scalar) open my $fh, ">", \$output or die "Unexpected open to scalar failure: +$!"; # save the default output file handle my $select_save = select($fh); # call your function call_function(); # clean up select($select_save); close $fh; # use output print "Got output: $output\n";

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (4)
As of 2024-04-20 02:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found