有人能帮帮我吗?在Perl中,以下两者的区别是什么:

exec "command";

and

system("command");

and

print `command`;

还有其他方法来运行shell命令吗?


当前回答

一般来说,我使用system、open、IPC::Open2或IPC::Open3,这取决于我想做什么。qx//操作符虽然简单,但在功能上限制太大,在快速攻击之外非常有用。我发现开放更方便。

系统:执行命令并等待返回

当您希望运行命令时,请使用system,不要关心它的输出,并且在命令执行完毕之前不希望Perl脚本执行任何操作。

#doesn't spawn a shell, arguments are passed as they are
system("command", "arg1", "arg2", "arg3");

or

#spawns a shell, arguments are interpreted by the shell, use only if you
#want the shell to do globbing (e.g. *.txt) for you or you want to redirect
#output
system("command arg1 arg2 arg3");

qx//或' ':运行一个命令并捕获它的STDOUT

当您希望运行一个命令,捕获它写入STDOUT的内容,并且在命令执行完毕之前不希望Perl脚本执行任何操作时,可以使用qx//。

#arguments are always processed by the shell

#in list context it returns the output as a list of lines
my @lines = qx/command arg1 arg2 arg3/;

#in scalar context it returns the output as one string
my $output = qx/command arg1 arg2 arg3/;

Exec:将当前进程替换为其他进程。

当你想运行一个命令,不关心它的输出,也不想等待它的返回时,使用exec和fork。系统实际上只是

sub my_system {
    die "could not fork\n" unless defined(my $pid = fork);
    return waitpid $pid, 0 if $pid; #parent waits for child
    exec @_; #replace child with new process
}

您可能还需要阅读waitpid和perlipc手册。

open:运行一个进程并创建一个指向它的STDIN或STDERR的管道

当您希望将数据写入进程的STDIN或从进程的STDOUT读取数据时(但不能同时执行这两项操作),请使用open。

#read from a gzip file as if it were a normal file
open my $read_fh, "-|", "gzip", "-d", $filename
    or die "could not open $filename: $!";

#write to a gzip compressed file as if were a normal file
open my $write_fh, "|-", "gzip", $filename
    or die "could not open $filename: $!";

IPC::Open2:运行一个进程并创建到STDIN和STDOUT的管道

当你需要读写进程的STDIN和STDOUT时,使用IPC::Open2。

use IPC::Open2;

open2 my $out, my $in, "/usr/bin/bc"
    or die "could not run bc";

print $in "5+6\n";

my $answer = <$out>;

IPC::Open3:运行一个进程并创建到STDIN, STDOUT和STDERR的管道

当您需要捕获进程的所有三个标准文件句柄时,请使用IPC::Open3。我会写一个例子,但它的工作方式与IPC::Open2基本相同,只是参数的顺序略有不同,还有第三个文件句柄。

其他回答

让我先引用一下手册:

Perldoc exec():

exec函数执行一个系统命令并且永不返回——如果你想让它返回,请使用system而不是exec

perldoc几千个():

做和exec LIST完全一样的事情,除了先做一个fork,并且父进程等待子进程完成。

与exec和system相反,反勾号不会给你返回值,而是给你收集的STDOUT。

perldoc‘String’:

(可能)插入的字符串,然后作为系统命令使用/bin/sh或等效命令执行。Shell通配符、管道和重定向将得到尊重。返回收集到的命令的标准输出;标准错误不受影响。


选择:

在更复杂的情况下,你想获取STDOUT, STDERR或返回码,你可以使用众所周知的标准模块,如IPC::Open2和IPC::Open3。

例子:

use IPC::Open2;
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'some', 'cmd', 'and', 'args');
waitpid( $pid, 0 );
my $child_exit_status = $? >> 8;

最后,IPC::Run from CPAN也值得一看…

一般来说,我使用system、open、IPC::Open2或IPC::Open3,这取决于我想做什么。qx//操作符虽然简单,但在功能上限制太大,在快速攻击之外非常有用。我发现开放更方便。

系统:执行命令并等待返回

当您希望运行命令时,请使用system,不要关心它的输出,并且在命令执行完毕之前不希望Perl脚本执行任何操作。

#doesn't spawn a shell, arguments are passed as they are
system("command", "arg1", "arg2", "arg3");

or

#spawns a shell, arguments are interpreted by the shell, use only if you
#want the shell to do globbing (e.g. *.txt) for you or you want to redirect
#output
system("command arg1 arg2 arg3");

qx//或' ':运行一个命令并捕获它的STDOUT

当您希望运行一个命令,捕获它写入STDOUT的内容,并且在命令执行完毕之前不希望Perl脚本执行任何操作时,可以使用qx//。

#arguments are always processed by the shell

#in list context it returns the output as a list of lines
my @lines = qx/command arg1 arg2 arg3/;

#in scalar context it returns the output as one string
my $output = qx/command arg1 arg2 arg3/;

Exec:将当前进程替换为其他进程。

当你想运行一个命令,不关心它的输出,也不想等待它的返回时,使用exec和fork。系统实际上只是

sub my_system {
    die "could not fork\n" unless defined(my $pid = fork);
    return waitpid $pid, 0 if $pid; #parent waits for child
    exec @_; #replace child with new process
}

您可能还需要阅读waitpid和perlipc手册。

open:运行一个进程并创建一个指向它的STDIN或STDERR的管道

当您希望将数据写入进程的STDIN或从进程的STDOUT读取数据时(但不能同时执行这两项操作),请使用open。

#read from a gzip file as if it were a normal file
open my $read_fh, "-|", "gzip", "-d", $filename
    or die "could not open $filename: $!";

#write to a gzip compressed file as if were a normal file
open my $write_fh, "|-", "gzip", $filename
    or die "could not open $filename: $!";

IPC::Open2:运行一个进程并创建到STDIN和STDOUT的管道

当你需要读写进程的STDIN和STDOUT时,使用IPC::Open2。

use IPC::Open2;

open2 my $out, my $in, "/usr/bin/bc"
    or die "could not run bc";

print $in "5+6\n";

my $answer = <$out>;

IPC::Open3:运行一个进程并创建到STDIN, STDOUT和STDERR的管道

当您需要捕获进程的所有三个标准文件句柄时,请使用IPC::Open3。我会写一个例子,但它的工作方式与IPC::Open2基本相同,只是参数的顺序略有不同,还有第三个文件句柄。

“exec”和“system”的区别在于,exec用“command”替换你当前的程序,并且永远不会返回到你的程序。另一方面,System会fork并运行'command',并在运行完成时返回'command'的退出状态。后勾号运行'command',然后返回一个表示其标准输出的字符串(无论它要打印到屏幕上的是什么)。

你也可以使用popen来运行shell命令,我认为有一个shell模块- 'use shell',它可以让你透明地访问典型的shell命令。

希望这能为你们解释清楚。

Perl的反撇号(')、system和exec之间有什么区别?

exec -> exec "command"; ,
system -> system("command"); and 
backticks -> print `command`;

exec

exec执行一个命令,从不恢复Perl脚本。它之于脚本就像return语句之于函数。

如果未找到命令,则exec返回false。它永远不会返回true,因为如果找到了命令,它就永远不会返回。返回命令的STDOUT、STDERR或退出状态也没有意义。您可以在perlfunc中找到关于它的文档,因为它是一个函数。

例如:

#!/usr/bin/perl
print "Need to start exec command";
my $data2 = exec('ls');
print "Now END exec command";
print "Hello $data2\n\n";

在上面的代码中,有三个print语句,但是由于exec离开脚本,只执行了第一个print语句。此外,exec命令的输出没有被分配给任何变量。

在这里,您只得到第一个打印语句的输出和在标准输出上执行ls命令的输出。

系统

系统执行一个命令,并且在命令执行完毕后恢复Perl脚本。返回值为命令的退出状态。您可以在perlfunc中找到有关它的文档。

例如:

#!/usr/bin/perl
print "Need to start system command";
my $data2 = system('ls');
print "Now END system command";
print "Hello $data2\n\n";

在上面的代码中,有三个打印语句。当脚本在执行system命令后恢复时,将执行所有三个print语句。

同样,运行system的结果被赋值给data2,但赋值为0 (ls的退出代码)。

在这里,您将获得第一个打印语句的输出,然后是ls命令的输出,然后是标准输出中最后两个打印语句的输出。

backticks(’)

与系统类似,用反引号括起命令将执行该命令,并且在命令执行完毕后恢复Perl脚本。与system相反,返回值是命令的STDOUT。Qx //等价于反撇号。您可以在perlop中找到关于它的文档,因为与system和exec不同,它是一个操作符。

例如:

#!/usr/bin/perl
print "Need to start backticks command";
my $data2 = `ls`;
print "Now END system command";
print "Hello $data2\n\n";

在上面的代码中,有三个打印语句,这三个语句都被执行了。ls的输出不会直接输出,而是赋值给变量data2,然后由最后的print语句输出。

exec

执行一个命令并且永不返回。 它就像函数中的return语句。

如果未找到命令,则exec返回false。 它永远不会返回true,因为如果找到了命令,它就永远不会返回。 返回命令的STDOUT、STDERR或退出状态也没有意义。 你可以在perlfunc中找到关于它的文档, 因为它是一个函数。

系统

执行命令,并在命令完成后继续执行Perl脚本。

返回值为命令的退出状态。 您可以在perlfunc中找到有关它的文档。

backticks

比如系统执行一个命令,你的perl脚本在命令完成后继续执行。

与系统相反,返回值是命令的STDOUT。 Qx //等价于反撇号。 您可以在perlop中找到有关它的文档,因为与system和execit不同,它是一个操作符。


其他的方式

上面所缺少的是异步执行命令的方法。 这意味着perl脚本和命令同时运行。 这可以通过开放来实现。 它允许您读取STDOUT/STDERR并写入命令的STDIN。 但它依赖于平台。

还有几个模块可以简化这个任务。 有IPC::Open2和IPC::Open3和IPC::Run,以及 Win32::Process::如果你在windows上创建。