Perl's backticks、system和exec之间的区别是什么?

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

exec "command";

而且

system("command");

而且

print `command`;

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

242992 次浏览

让我先引用一下手册:

perldoc exec ():

exec函数执行一个系统命令和从来没有回报——如果你想让它返回,使用系统而不是执行

perldoc系统():

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

执行系统相反,反勾号不会给你返回值,而是收集的STDOUT。

perldoc & # x0060;字符串# x0060;:

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


选择:

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

例子:

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

最后,CPAN中的IPC:运行也值得一看…

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

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

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

执行

执行一个命令和从来没有回报。 它就像函数中的return语句

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

系统

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

返回值为命令退出状态。 你可以在< >强perlfunc < / >强中找到关于它的文档

引号的

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

system相反,返回值是命令的STDOUTqx//相当于反撇号。 你可以在< >强perlop < / >强中找到关于它的文档,因为与system和__abc2不同,它是一个操作符


其他的方式

上面所缺少的是异步执行命令的方法。 这意味着perl脚本和命令同时运行。 这可以通过< >强open < / >强来实现。 它允许你读取STDOUT/STDERR并写入你的命令的STDIN。 不过它是依赖于平台的 还有几个模块可以简化这个任务。 有IPC::Open2IPC::Open3IPC::Run,以及 Win32::Process::Create如果你是在windows上

一般来说,我使用systemopenIPC::Open2,或IPC::Open3,这取决于我想做什么。qx//操作符虽然简单,但在功能上过于受限,在快速hack之外非常有用。我发现open更方便。

system:运行一个命令并等待它返回

当你想要运行一个命令时,使用system,不要关心它的输出,并且在命令完成之前不希望Perl脚本做任何事情。

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

#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

当你想要运行一个命令时,使用qx//,捕获它写入STDOUT的内容,并且在命令完成之前不希望Perl脚本做任何事情。

#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:将当前进程替换为另一个进程。

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

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
}

你可能还想阅读waitpidperlipc手册。

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:留有妥协:运行一个进程并创建一个指向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基本相同,只是参数的顺序略有不同,还有第三个文件句柄。

Perl的反引号(`)、systemexec之间有什么区别?

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

exec

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

如果没有找到命令,exec返回false。它永远不会返回true,因为如果找到了命令,它就永远不会返回。返回命令的STDOUTSTDERR或退出状态也没有意义。你可以在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命令输出没有被分配给任何变量。

在这里,你只能得到第一个print语句的输出和在标准输出时执行ls命令的输出。

system

system执行一个命令,命令执行完成后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";

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

同样,运行system 的结果分配给data2,但分配的值是0(来自ls的退出代码)。

在这里,你将得到第一个print语句的输出,然后是ls命令的输出,然后是标准输出的最后两个print语句的输出。

引号(`)

system类似,用反引号括起命令会执行该命令,并且在命令执行完毕后恢复Perl脚本。与system相反,返回值是命令的STDOUTqx//相当于反勾号。你可以在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";

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