Sam
Sam

Reputation: 2371

Running a shell command in a perl loop, using a variable from the perl loop

I need to run a shell command within a perl script(It needs to be a shell command) but I need to use a variable in a perl loop

Ex. doing something like

#!/usr/bin/perl
for my $i (0..9) {
     `echo $i`;
}

should produce the output

0
1
2
3
4
5
6
7
8
9

Upvotes: 2

Views: 2624

Answers (2)

zdim
zdim

Reputation: 66964

You can do it in several ways, depending on what exactly is needed. Generally, this involves use of system, backticks (with operator form qx), or open. There is also a number of great modules for it.

The qx returns its STDOUT to the program. If you need it assign it to a variable.

for my $i (0..9) {
    my $cmd = "external-command $i";
    my $cmdout = qx($cmd);             # needs error checking ($?)
    print $cmdout;                     # process as needed
}

The output can also be assigned to an array, when each line becomes one array element. Depending on what your command is you may have to pay close attention to how to quote it correctly, and String::ShellQuote can help a lot. If you want to get the command's STDERR as well use

my $cmd = "external-command $i 2>&1";

See qx in perlop (or readpipe), which also discusses error checking; also see $? in pervar.

If you don't need the command's output in your script, or specifically want it to wind up together with your script's other output, use system. Commands run by it inherit the script's STDOUT and STDERR so what they print to standard streams will go where your script's output goes (unless it is redirected by the command invocation).

for my $i (0..9) {
    my $cmd = "external-command $i";
    my $ret = system($cmd);
    if ($ret != 0) {
        warn "Error running $cmd: $ret";
        # interrogate further, see documentation for 'system'
    }
}

The error handling above is rudimentary, see docs for more. Finally, there are various forms of open that run a process. For example, see it in perlfaq8, along with a full review of what you are asking.

And then there are modules, that make this kind of work far easier and better. From simple to more capable, some of well-known ones are IPC::System::Simple, Capture::Tiny, IPC::Run3, and IPC::Run. Also see links (examples) assembled in this post, for example.

A command can be executed via a shell or not (but via execvp) depending on how exactly it is invoked, as discussed in the docs. The phrase "shell command" strictly refers to a facility provided by the shell itself, in which case you of course want to run it that way. However, it is also often used for a program that we normally execute by typing in a terminal, so it gets executed by the shell. In this case you may (or may not) want to bypass the shell.

Also note that the above all block (do not return control before completing), so the script continues only after they're done. This seems to be what you want.

Upvotes: 5

GWP
GWP

Reputation: 131

If you just want to pass through the shell output, simply do

print STDOUT `echo $i`;

Upvotes: 0

Related Questions