32
$ cat test.pl
my $pid = 5892;
my $not = system("top -H -p $pid -n 1 | grep myprocess | wc -l");
print "not = $not\n";
$ perl test.pl
11
not = 0
$

I want to capture the result i.e. 11 into a variable. How can I do that?

Nikhil Jain
  • 8,232
  • 2
  • 25
  • 47
Lazer
  • 90,700
  • 113
  • 281
  • 364
  • 1
    Also see [What's the differences between system and backticks and pipes in Perl?](http://stackoverflow.com/q/797127) – jww Jun 29 '16 at 02:16

6 Answers6

72

From Perlfaq8:

You're confusing the purpose of system() and backticks (``). system() runs a command and returns exit status information (as a 16 bit value: the low 7 bits are the signal the process died from, if any, and the high 8 bits are the actual exit value). Backticks (``) run a command and return what it sent to STDOUT.

$exit_status   = system("mail-users");
$output_string = `ls`;

There are many ways to execute external commands from Perl. The most commons with their meanings are:

  • system() : you want to execute a command and don't want to capture its output
  • exec: you don't want to return to the calling perl script
  • backticks : you want to capture the output of the command
  • open: you want to pipe the command (as input or output) to your script

Also see How can I capture STDERR from an external command?

Hi-Angel
  • 4,933
  • 8
  • 63
  • 86
Nikhil Jain
  • 8,232
  • 2
  • 25
  • 47
  • 3
    Worth noting: if you want the output to be split on newlines *(which is probably the case in the example with with `ls`)*, just assign it to "array" variable. I.e. replace `$output_string = \`ls\`` with `@output_string = \`ls\`` – Hi-Angel Apr 10 '20 at 09:45
16

The easiest way is to use the `` feature in Perl. This will execute what is inside and return what was printed to stdout:

 my $pid = 5892;
 my $var = `top -H -p $pid -n 1 | grep myprocess | wc -l`;
 print "not = $var\n";

This should do it.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Peter Tillemans
  • 34,983
  • 11
  • 83
  • 114
9

Try using qx{command} rather than backticks. To me, it's a bit better because: you can do SQL with it and not worry about escaping quotes and such. Depending on the editor and screen, my old eyes tend to miss the tiny back ticks, and it shouldn't ever have an issue with being overloaded like using angle brackets versus glob.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ken Hylton
  • 91
  • 1
  • 2
4

Using backtick or qx helps, thanks everybody for the answers. However, I found that if you use backtick or qx, the output contains trailing newline and I need to remove that. So I used chomp.

chomp($host = `hostname`);
chomp($domain = `domainname`);
$fqdn = $host.".".$domain;

More information here: http://irouble.blogspot.in/2011/04/perl-chomp-backticks.html

Soumya Kanti
  • 1,429
  • 1
  • 17
  • 28
  • chomp really is a strange beast... i don't get it, why $host = `hostname` ; $out = chomp($host) is not working... – Martin T. Jun 05 '20 at 11:04
  • `chomp` returns the number of characters it removed after it modifies your argument. You almost never care about what `chomp` returns. – brian d foy Jan 17 '21 at 06:18
1

Use backticks for system commands, which helps to store their results into Perl variables.

my $pid = 5892;
my $not = ``top -H -p $pid -n 1 | grep myprocess | wc -l`; 
print "not = $not\n";
brian d foy
  • 129,424
  • 31
  • 207
  • 592
Crazy coder
  • 99
  • 10
0

Also for eg. you can use IPC::Run:

use IPC::Run qw(run);

my $pid = 5892;
run [qw(top -H -n 1 -p), $pid],
    '|', sub { print grep { /myprocess/ } <STDIN> },
    '|', [qw(wc -l)],
    '>', \my $out;

print $out;
  • processes are running without bash subprocess
  • can be piped to perl subs
  • very similar to shell
3ED
  • 115
  • 1
  • 4