nims nims - 1 year ago 64
Perl Question

while loop to execute a command multiple times and store the output in a different variable each time

I want to execute a command thrice, and store the output of the command execution in a different variable each time. The below code is to store it in the same variable each time. How do i store in different variable ?

int $i=0;
while ( $i< 3 ) {
$a = ( " command gets executed her " );
$i = $i+1 ;

I want the output to be stored in three different variables say $a $ b and $ c.

Answer Source

You can store output in an array

my @output;

for (1..3) {
   my $cmd = '...';
   push @output, scalar qx($cmd);

Now elements of @output have the output of consecutive command runs.

Note that qx (backticks) can return either a string with all lines of output from a command, or a list with lines of the output being the elements, depending on the context in which it is called.

my @out = qx(ls -l .);  # @out elements have lines from output
my $out = qx(ls -l .);  # all lines from output are in string $out

Since push takes a list to push, the list context is imposed and (without the scalar) multiple lines from a command would be added as separate elements. But scalar forces the scalar context, and then the whole output of each command goes into a string, which is added as an element each time through. So we get an array with three elements, each being a (potentially multi-line) string. Thanks to ThisSuitIsBlackNot for the comment.

How you are getting the output of a command is a different question. Here I've assumed that the "command" implies an external command which prints to its STDOUT, and omitted error checking. It is probably a good idea to run qx separately, check for errors, and only then put output on the array.

Per the specific requirement to assign to actual variables, one way

my ($out1, $out2, $out3);

for ($out1, $out2, $out3) {
    my $cmd = '...';
    $_ = qx($cmd);

Here you have to explicitely list variable names, both to declare them and to loop over them. That doesn't make for very good code, since you have to list all variables, it is harder to keep track of things, and any changes that come have to be applied to multiple places.

If you are thinking about constructing variable names on the fly (inside for (1..3) for example) in order to avoid dealing with lists of named variables, you'd be messing with symbolic references -- and you don't want to be doing that. A lot has been said against it over time and it is a very clearly discouraged practice. See, for example, this post. For one thing, use strict doesn't allow it.

If you insist on having names, you could use a hash with key names built at runtime

my %out;

for (1..3) {
    my $cmd = '...';
    my $key = 'o' . $_;  # name keys as 'o1', 'o2', etc
    $out{$key} = qx($cmd);

for (sort keys %out) {
    print "$_ => $out{$_}\n";

Note that you again have to make up those specific key names and keep track of them.

I'd advise to use an array, if at all possible. When you process that you can always assign to a named variable as you loop over it, for example. Or, better, to reconsider the design that leads to this need.