Overview
有很多时候,我们需要在perl
脚本中调用系统命令,比如调用系统的某个软件做一件事。也可以说是在perl
脚本中调用外部命令,比如在一个perl
脚本中调用另一个perl
脚本。
有很多种方式可以实现这个目的,这里我列出来3中常见的方式,并以一个例子说明这三种方式的不同之处。
1. 被调用的perl
脚本
我们在一个perl
脚本(取名为testSystemCall.pl
)中调用另一个脚本(取名为printCallInfo.pl
)。printCallInfo.pl
中内容如下:
#!/usr/bin/perl -w
# usage: perl printCallInfo.pl number
# number: an Integer
use strict;
use warnings;
my $countNumber = $ARGV[0] or die "Need to input an integer on the command line\n";
print "This perl script is called $countNumber times\n";
使用方法已经在脚本中说明,比如使用:
perl printCallInfo.pl 5
屏幕上就会显示:
This perl script is called 5 times
2. 调用脚本testSystemCall.pl
我们在脚本中分别查看使用以下三种方式调用printCallInfo.pl
:
- system("command");
- exec("command");
- `command`;
testSystemCall.pl
脚本内容如下:
#!/usr/bin/perl -w
# usage: perl testSystemcall.pl number
# number : an enum number
# 1: use system("command")
# 2: use exec("command")
# 3: use `command`;
use strict;
use warnings;
my $exceType = $ARGV[0] or die "Need to input an integer(1,2,3) on the command line\n";
print "Begin loop to invoke system call: \n";
for(my $i=1; $i<=5;$i++)
{
($exceType == 1) and system("perl printCallInfo.pl $i");
($exceType == 2) and exec("perl printCallInfo.pl $i");
($exceType == 3) and `perl printCallInfo.pl $i`;
}
print "End loop.\n";
这个脚本需要指定一个1或者2或者3的整数,指定1代表执行system("perl printCallInfo.pl $i")
,指定2或者3以此类推。
这里注意or
和and
的使用,也可以分别使用||
和&&
代替。巧妙使用这种方式可以节省很多if else
语句。
2.1 system("command")
(推荐)
使用该命令将开启一个子进程执行引号中的命令,父进程将等待子进程结束并继续执行下面的代码。
使用命令:
perl testSystemCall.pl 1
执行了system("perl printCallInfo.pl $i");
,得到下面的结果:
Begin loop to invoke system call:
This perl script is called 1 times
This perl script is called 2 times
This perl script is called 3 times
This perl script is called 4 times
This perl script is called 5 times
End loop.
结果在意料之中。
2.2 exec("command");
效果同system命令类似,区别是不会开启子进程,而是取代父进程,因此执行完引号中的命令后进程即结束。一般和fork配合使用。
使用命令:
perl testSystemCall.pl 2
执行了exec("perl printCallInfo.pl $i");
,得到下面的结果:
Begin loop to invoke system call:
This perl script is called 1 times
结果出乎意料,如果你刚才还不太理解这一小节引用的那句话,现在应该明白了。exec
命令取代了父进程,执行一次结束之后进程结束,因为这个进程就是父进程本身,因此父进程也跟着结束了。testSystemCall.pl
脚本中的后续内容也就不会执行了。
3. `command`
使用反引号调用外部命令能够捕获其标准输出,并按行返回且每行结束处附带一个回车。反引号中的变量在编译时会被内插为其值。
好像更不好理解了。先执行一下:
perl testSystemCall.pl 3
执行了`perl printCallInfo.pl $i
`;这句代码,显示如下:
Begin loop to invoke system call:
End loop.
什么都没打印,好像没执行一样。其实已经执行了,只是`perl printCallInfo.pl $i
`没有把printCallInfo.pl
中的输出直接输出到屏幕上,而是返回给了testSystemCall.pl
,只是我们在testSystemCall.pl
中并没有接收这个返回值。
我们修改一下testSystemCall.pl
,将
($exceType == 3) and `perl printCallInfo.pl $i`;
改成:
($exceType == 3) and print `perl printCallInfo.pl $i`;
我们将`perl printCallInfo.pl $i`返回的内容再重新打印出来,重新执行:
perl testSystemCall.pl 3
显示如下:
Begin loop to invoke system call:
This perl script is called 1 times
This perl script is called 2 times
This perl script is called 3 times
This perl script is called 4 times
This perl script is called 5 times
End loop.
显示内容是不是更符合我们的期望了~