Overview
有很多时候,我们需要在perl
脚本中调用系统命令,比如调用系统的某个软件做一件事。也可以说是在perl
脚本中调用外部命令,比如在一个perl
脚本中调用另一个perl
脚本。
有很多种方式可以实现这个目的,这里我列出来3中常见的方式,并以一个例子说明这三种方式的不同之处。
1. 被调用的perl
脚本
我们在一个perl
脚本(取名为testSystemCall.pl
)中调用另一个脚本(取名为printCallInfo.pl
)。printCallInfo.pl
中内容如下:
1 2 3 4 5 6 7 8 9 10 | #!/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"; |
使用方法已经在脚本中说明,比如使用:
1 | perl printCallInfo.pl 5 |
屏幕上就会显示:
1 | This perl script is called 5 times |
2. 调用脚本testSystemCall.pl
我们在脚本中分别查看使用以下三种方式调用printCallInfo.pl
:
- system("command");
- exec("command");
- `command`;
testSystemCall.pl
脚本内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #!/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")
(推荐)
使用该命令将开启一个子进程执行引号中的命令,父进程将等待子进程结束并继续执行下面的代码。
使用命令:
1 | perl testSystemCall.pl 1 |
执行了system("perl printCallInfo.pl $i");
,得到下面的结果:
1 2 3 4 5 6 7 | 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配合使用。
使用命令:
1 | perl testSystemCall.pl 2 |
执行了exec("perl printCallInfo.pl $i");
,得到下面的结果:
1 2 | Begin loop to invoke system call: This perl script is called 1 times |
结果出乎意料,如果你刚才还不太理解这一小节引用的那句话,现在应该明白了。exec
命令取代了父进程,执行一次结束之后进程结束,因为这个进程就是父进程本身,因此父进程也跟着结束了。testSystemCall.pl
脚本中的后续内容也就不会执行了。
3. `command`
使用反引号调用外部命令能够捕获其标准输出,并按行返回且每行结束处附带一个回车。反引号中的变量在编译时会被内插为其值。
好像更不好理解了。先执行一下:
1 | perl testSystemCall.pl 3 |
执行了`perl printCallInfo.pl $i
`;这句代码,显示如下:
1 2 | Begin loop to invoke system call: End loop. |
什么都没打印,好像没执行一样。其实已经执行了,只是`perl printCallInfo.pl $i
`没有把printCallInfo.pl
中的输出直接输出到屏幕上,而是返回给了testSystemCall.pl
,只是我们在testSystemCall.pl
中并没有接收这个返回值。
我们修改一下testSystemCall.pl
,将
1 | ($exceType == 3) and `perl printCallInfo.pl $i`; |
改成:
1 | ($exceType == 3) and print `perl printCallInfo.pl $i`; |
我们将`perl printCallInfo.pl $i`返回的内容再重新打印出来,重新执行:
1 | perl testSystemCall.pl 3 |
显示如下:
1 2 3 4 5 6 7 | 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. |
显示内容是不是更符合我们的期望了~