We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you two Citrix podcasts. Learn about 2020 trends and get answers to your biggest Citrix questions!Listen Now

x

Using Perl open with pipes

mcmike
mcmike asked
on
Medium Priority
551 Views
Last Modified: 2008-03-04
I have a question regarding the 'piping' of output
via an 'open' command.  Essentially I am invoking a
database connection using the database's proprietary command line
utility and I will be passing SQL commands through
the file handle.  My problem lies in effeciently capturing
to database output into a buffer or filehandle.  Presently
I am 'piping' the output to another perl script which
uses 'while (<>)' to process the stream and load a buffer.
However I want to avoid invoking another perl script and
would rather load a buffer in the subroutine and pass
that back to the calling routine.  Below is an example of
what I am trying to do.  I am using 'sh' for the sake of
the example, but this is where I would be invoking the
database utility and the following 'print XXX "..."' is
where I would I would be passing the database commands.
I can not find another way besides invoking the second
perl script (catcher.pl) to capture the data.

----------------------

#!/export/home/local/bin/perl
use English;

&getTest;

sub getTest
{
open(XXX,"| sh | catcher.pl");
print XXX "echo 'this is a test1'\n";
print XXX "echo 'this is a test2'\n";
print XXX "exit\n";

#I DO NOT WANT TO INVOKE ANOTHER SCRIPT TO
#TO HANDLE THE OUTPUTSTREAM.  I WOULD LIKE TO DO
#SOMETHING LIKE:
#open(XXX,"| sh | @buffer");
#OR
#open(XXX,"| sh | $fileHandle");
#SO THAT I CAN BE ABLE TO LOOP THROUGH AND
#PROCESS THE BUFFER OR FILE HANDLE LATER
#IN THE PROGRAM AND MANIPULATE THE INDIVIDUAL
#OUTPUT ELEMENTS.  BUT HOW DO YOU DO THIS WITHOUT
#INVOKING ANOTHER SCRIPT TO CATCH THE STREAM?
#IDEALLY ALL OF THE OUPUT WOULD BE PIPED TO A
#BUFFER.  THEN I COULD PASS THIS BUFFER BACK TO
#THE CALLING ROUTINE OR ANOTHER SUBROUTINE.

close XXX;
}

-------------catcher.pl--------------

#!/export/home/local/bin/perl
use English;
while (<>)
{
   push @buffer, $_;
}
$cnt=1;
foreach $element (@buffer)
{
   print "LINE $cnt: $element";
   $cnt+=1;
}

---------

Any comments/suggestion/solutions on a better method
of capturing output would be very much appreciated.

Thank you
Michael McGrattan

Comment
Watch Question

ozo
CERTIFIED EXPERT
Most Valuable Expert 2014
Top Expert 2015

Commented:
One way to do it:

open(XXX,"echo \"echo 'this is a test1'\necho 'this is a test2'\nexit\n\"| sh |") || die $!;
while( <XXX> ){
          print "LINE $.: $_";
}
close XXX or die $!;

Another:

open(XXX,"| sh > catcher.tmp") || die $!
print XXX "echo 'this is a test1'\n";
print XXX "echo 'this is a test2'\n";
print XXX "exit\n";
close XXX or warn $!;
open(XXX,"<catcher.tmp") || die $!;
while( <XXX> ){ ... }

Another:

use IPC::open2;


Author

Commented:
Thank you for you input.  I found that the
'use IPC::open2' was what I needed.
This allows me to capture input/output nicely.

Thanks again
Michael McGrattan
CERTIFIED EXPERT
Most Valuable Expert 2014
Top Expert 2015
Commented:
use IPC::Open2;
$pid = open2(\*BUFFER,\*XXX,"sh") || die $!;
print XXX "echo 'this is a test1'\n";
print XXX "echo 'this is a test2'\n";
print XXX "exit\n";
close XXX or warn "error closing |$pid $!";
while( <BUFFER> ){
           print "LINE $.: $_";
}
close BUFFER or warn "error closing $pid| $!";

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts
ozo
CERTIFIED EXPERT
Most Valuable Expert 2014
Top Expert 2015

Commented:
or

print XXX <<ZZZ;
echo 'this is a test1'
echo 'this is a test2'
exit
ZZZ


Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.