moderated >> Print output of subroutines captured in backticks?

by Mr. Nice Guy » Wed, 21 Oct 2009 09:58:04 GMT

Hi,

In ksh, I can do something like this:

blat()
{
print "blat says foo"
return 0
}
junk=`blat`
rv=$?

In which case, "$junk" holds "blat says foo", while "$rv" holds 0, or
whatever blat() actually returns. This is really useful in capturing
an error message from the function, as well as the actual return code.

How would I do this in Perl, where I capture the print() statements of
the sub in a variable, but the return value separately? Something
along the lines of:

sub blat ()
{
print "blat says foo";
return 0;
}

my( $junk, $rv );

$junk = `blat`; # -- this doesn't actually work, since blat() isn't
an external executable
$rv = $?;

What I want is whatever blat() might have output via print()
statements into $junk rather than STDOUT, but the return value of the
function in a separate variable; $rv in this case.

I know I can use something like:

sub blat ()
{
print "This will be sent to STDOUT\n";
die( "This will get caught by the eval{ ... }" );
}

eval { blat() };
print $@ if $@;

But this is different.

A. i'm limited to whatever I provide in die(), rather than any or all
output from the function. Don't get me wrong: "eval { ... }" is
useful, and I do use this.

B. die()'s return value is going to be 1 in most, if not all, cases,
not whatever I want to return. Unless there's a way to return a
different value; setting $! didn't seem to work.

moderated >> Print output of subroutines captured in backticks?

by Andrzej Adam Filip » Fri, 23 Oct 2009 05:26:53 GMT



Use "select" to redirect output of "print without specific file-handle"
to string (IO::String);

use IO::String;
my ($returnCode, $output);
my $io = IO::String->new($output);
my $oldfh = select($io);
eval { $returnCode = &blat() };
select($oldfh);

print "returnValue=$returnCode\n";
print "output=\n",$output,"\n";

--
[pl>en Andrew] Andrzej Adam Filip : XXXX@XXXXX.COM : XXXX@XXXXX.COM
It is far more impressive when others discover your good qualities without
your help.
-- Miss Manners

moderated >> Print output of subroutines captured in backticks?

by Keith Thompson » Sat, 24 Oct 2009 09:21:35 GMT

Andrzej Adam Filip < XXXX@XXXXX.COM > writes:
[...]

If you have Perl 5.8 or better, you don't need IO::String. Quoting
the IO::String documentation:

Note that perl-5.8 and better has built-in support for "in memory"
files, which are set up by passing a reference instead of a filename to
the open() call. The reason for using this module is that it makes the
code backwards compatible with older versions of Perl.

--
Keith Thompson (The_Other_Keith) XXXX@XXXXX.COM < http://www.ghoti.net/ ~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Similar Threads

1. capture output from print command to variable in perl

i know its possible to get the epoch time in perl using the command
print time;
how can i capture this in a variable in a perl script? i've got a
feeling i'm missing something fundamental from my perl knowledge but
can't find out how to do it in the books i've been through.

2. Capturing the results from Expect with backtick - Perl

3. Suppressing output from backtick operator

How does one do this? I have the output in a script set to a variable such as:
my $var = `cmd --arg1 --arg2 | egrep 'This|That'` and I don't want to see it as the script is run.

Thank you,
jlc

4. Using backtick operator output and feeding it into array - Perl

5. Redirecting output of command inside backticks

I am using

`bash_script.sh` inside a perl_script.

How do I redirect the output and error output of command1 to *whatever*
is the stdout and stderr of the perl_script.

The perl_script can be called from commandline like

$ ./perl_script

or 

$ ./perl_script > perl_script.out 2>&1

Thanks a lot.

6. backtick not printing the 'echo'ed line - Perl

7. capture unix cmd outputs

Hello. I am trying to print the output of unix command typed in a 
LabEntry in the Text widget upon button click. The code is modified 
version of the one avialable in perl/tk FAQ website. But it gives "no 
such file or directory" error. Any help is appreciated. 

Thnx in advance.
S



#!/usr/local/bin/perl -w
use Tk;
require Tk::BrowseEntry;

# main window
my $mw = MainWindow->new(-title => "my perl/tk");

    my $cFrame = $mw->Frame(
	        -relief      => 'ridge',
    	    -borderwidth => 2,
    		)->pack(-side => 'top',	
    						-fill => 'x', 
							-anchor => 'e', 
							-expand => 1);
    my $c2Frame = $cFrame->Frame(
    		)->pack(-side => 'top',	
    						-fill => 'x', 
							-anchor => 'e', 
							-expand => 1);
	my $cmd = "ls";						
	$c2Frame->LabEntry(-textvariable => \$cmd, 
    			    -label => "Cmd: ", -labelPack => [-side => 
'left'],
            )->pack(-side => 'left', -fill => 'x', -anchor => 'e', -
expand => 1);

    my $dFrame = $mw->Frame(
	        -relief      => 'ridge',
    	    -borderwidth => 2,
    		)->pack(-side => 'top',	
    						-fill => 'both', 
							-expand => 1);
    my $d1Frame = $dFrame->Frame(
	        )->pack(-side => 'top',	
    						-fill => 'x', 
							-expand => 1);
    my $d2Frame = $dFrame->Frame(
	        )->pack(-side => 'top',	
    						-fill => 'both', 
							-expand => 1);
	$d1Frame->Label(-text => "Log:")
				->pack(-side => 'left', 
							-anchor => 'w', 
							-expand => 0);
	$d1Frame->Label(-text => " ")
				->pack(-side => 'left', 
							-fill => 'x', 
							-anchor => 'w', 
							-expand => 1);
	my $cmdBtn = $d1Frame->Button(-text => "Run", -command=> 
\&printCmd)
				->pack(-side => 'left', 
							-anchor => 'e', 
							-expand => 0);
	my $t = $d2Frame->Text(-wrap => 'word');	# used -state => 
'normal' | 'disabled' to affect editing!!
	$t->pack(-side => 'bottom', -fill => 'both', -expand => 1);
	$t->menu(undef);	# stop the menu 


MainLoop;


sub printCmd {

	print "Here! ", $cmd, "\n";

	open(H, '$cmd') or die "Nope: $!";
	select H ;
#	$| = 1 ; 
	select STDOUT ;
#    $mw->fileevent(H, 'readable', [\&fill_text_widget, $t]);
    $mw->fileevent(H, [\&fill_text_widget]);

    sub fill_text_widget {
   
        my($widget) = @ARG;
        $ARG = <H>;
        $t->insert('end', $ARG);
        $t->yview('end');
    
    } # end fill_text_widget




#my @files = `ls -l | grep -v \"^d\" | awk \'{print \$9\}\'`;
#foreach $file (@files)
#{
#print "$file ";
#}

}

1;
__END__

8. run perl script and capture the output