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

Hello PerlMonks,

I need your advise on giving input and collecting output from a perl script using another perl script.

Here is a description of what I am trying to do:

I am using someone else's perl script compare.pl (This script is part of a package, that contains two *.pl files, six *.pm files and 5 text files). compare.pl takes input form STDIN and gives out put as a text file. I need to run compare.pl many times and collect all output text files for further processing.

Now, I wrote a short perl script that 1) calls compare.pl program, 2) gives input to it, 3) reads generated output-text-file and 4) stores output-text-file-data in memory. When this is finished, my script calls compare.pl once again and the sequence (1-2-3-4) repeats for n-times.

I personally feel, writing output of compare.pl to hard disc and reading output-file from hard disc is a time consuming and inefficient process. I would rather like to call compare.pl from my script, give input to it, save output in memory (as a 2 dimensional array, with every sub-array containing output of single run of compare.pl) and finally write all contents of 2 dimensional array to a text or csv file.

How should I do it ?

compare.pl has a hidden answer to my query. This script, compare.pl calls other programs in the package (*.pm files), gives input and takes output through Exporter function. I am thinking, should I modify compare.pl to compare.pm and use the same method to give input and collect output OR should I use IPC::open(3) to call compare.pl, give input and collect output ?

I have not created any library till now, and have not used any perl module either. Any suggestions ?

TIA

Replies are listed 'Best First'.
Re: How to give input and collect output of a perl script using another perl script
by GrandFather (Saint) on Mar 23, 2011 at 10:05 UTC

    I'd vote for modify compare.pl into compare.pm. Actually I'd copy compare.pl to Compare.pm and add:

    package Compare; # modified original contents of compare.pl here 1;

    The package line at the top and the (implicit return) 1 at the end are pretty much all the extra stuff you need. In your calling script you:

    #!/usr/bin/perl use strict; use warnings; use Compare; ... Compare::SomeSubInTheCompareModule ();

    Notice the way sub SomeSubInTheCompareModule is called by using the package name. Aside from that icing a sub in Compare is called and used in just the same way as a sub in the .pl file.

    True laziness is hard work

      GF: Thank you for short intro to perl modules

      I am learning to use perl modules with a small example. Please go through below example, I have a couple of questions at the end

      test2.pl is a script that uses perl module test.pm

      Contents of test.pl

      #!/usr/bin/perl use strict; use warnings; use test; my @gaga = ("paras", "kansas"); my ($x, $y) = test::test(@gaga); print "$x\n$y\n";

      contents of test.pm

      package test; sub test { my $tag = $_[0]; $tag =~ s/p/n/; my $bag = $_[1]; $bag =~ s/k/p/; return $tag, $bag } 1;

      output

      napas panas

      above script and module work very well. What I don't understand is..

      Query-1: What is function of 1 at the end of test.pm ?

      To see whether module works without a subroutine, I modified test.pm, by removing subroutine (see code below)

      Contents of test2.pl

      #!/usr/bin/perl use strict; use warnings; use test; my @gaga = ("paras", "kansas"); my ($x, $y) = test(@gaga); print "$x\n$y\n";

      contents of test.pm

      package test; my $tag = $_[0]; $tag =~ s/p/n/; my $bag = $_[1]; $bag =~ s/k/p/; return $tag, $bag 1;

      Expected result is...

      napas panas

      But error message reads...

      test.pm did not return a true value at test2.pl line 4. BEGIN failed--compilation aborted at test2.pl line 4.

      Query-2: Is it must to have a subroutine inside a module ?

        1/ When you use or require a module Perl loads it and compiles it. Perl then executes any "main line" code in the module and checks that the result is true. For most modules the "main line" code may be as simple as 1; which is equivalent to return 1; and returns the true result Perl expects. More interesting work done by a module during loading includes initialising variables and perhaps performing any other one time house keeping that the module may need (even including connecting to a database for example).

        From 1/ above you may figure out that the load process will see return $tag, $bag 1; as the result from loading the module. If you had used strictures in the module (use strict; use warnings;), which you should always do, you would have received a number of "Use of uninitialized value" messages too. Because there are no parameters passed in $tag and $bag are undefined which is false so the module load fails. Module Test (note the upper case first letter - it's important) should look like:

        use strict; use warnings; package Test; sub SubInTest { my $tag = $_[0]; $tag =~ s/p/n/; my $bag = $_[1]; $bag =~ s/k/p/; return $tag, $bag; } 1;

        Note that strictly lower case module names are reserved by Perl for use as pragmata such as strict and warnings. You can use such names, but shouldn't in case Perl decides it wants to in some future version.

        2/ By now it should be clear that, except for unusual modules (which only export data for example), it is futile to have a subroutine-less module because you can't execute any code in it after it's been loaded.

        True laziness is hard work