在perl中反勾号(``),system和exec都用来执行命令,这篇文章将给我们介绍它们各自的使用方法,联系,以及区别。

一、使用方法

1.       反勾号(``)

首先,我们有命令输入操作符,也叫反勾号操作符,因为它看起来象这样:
$info = `finger $user`;

一个用反勾号(技术上叫重音号)引起的字串首先进行变量替换,就象一个双引号引起的字串一样。得到的结果然后被系统当作一个命令行,而且那个命令的输出成为伪文本的值。(这是一个类似 Unix shell 的模块。)在标量环境里,返回一个包含所有输出的字串。在列表环境里,返回一列值,每行输出一个值。(你可以通过设置 $/ 来使用不同的行结束符。)
每次计算伪文本的时候,该命令都得以执行。该命令的数字状态值保存在 $?(参阅第二十八章获取 $? 的解释,也被称为 $CHILD_ERROR )。和这条命令的 csh 版本不同的是,对返回数据不做任何转换——换行符仍然是换行符。和所有 shell 不同的是,Perl 里的单引号不会隐藏命令行上的变量,使之避免代换。要给 shell 传递一个 $,你必须用反斜杠把它隐藏起来。我们上面的 finger 例子里的 $user 被 Perl 代换,而不是被 shell。(因为该命令 shell 处理,参阅第二十三章,安全,看看与安全有关的内容。)
反勾号的一般形式是 qx//(意思是“引起的执行”),但这个操作符的作用完全和普通的反勾号一样。你只要选择你的引起字符就行了。有一点和引起的伪函数类似:如果你碰巧选择了单引号做你的分隔符,那命令行就不会进行双引号代换;
$perl_info = qx(ps $$); # 这里 $$ 是 Perl 的处理对象 $perl_info = qx'ps $$'; # 这里 $$ 是 shell 的处理对象
下面是一个例子:
在笔者的F盘中存在一个perl文件F:\\Demo3.pls,它的作用就是被另外一个程序F:\\Demo1.pls调用,然后F:\\Demo3.pls读取log3.log中的数据。

Demo3.pls

#!/usr/bin/perl -w

use strict;
use warnings;

unless(open(FILE_H,"<F:\\log3.log")){
    print "Can not open the file";
}

my @str = <FILE_H>;

my $count = @str;
close(FILE_H);

for(my $i = 0;$i<$count;$i++){
   print "$str[$i]";
}

Demo.pls

#!/usr/bin/perl –w

my @str = qx/perl F:\\Demo3.pls/;#或者` perl F:\\Demo3.pls `效果#一样

print "@str";

Log3.log

首先,我们有命令输入操作符,也叫反勾号操作符,因为它看起来象这样:

$info = `finger $user`;

一个用反勾号(技术上叫重音号)引起的字串首先进行变量替换,就象一个双引号引起的字串一样。得到的结果然后被系统当作一个命令行,而且那个命令的输出成为伪文本的值。(这是一个类似 Unix shell 的模块。)在标量环境里,返回一个包含所有输出的字串。在列表环境里,返回一列值,每行输出一个值。(你可以通过设置 $/ 来使用不同的行结束符。)

代码解释,当执行Demo.pls时,my @str = qx/perl F:\\Demo3.pls/;这一句会被操作系统调用并且启动Demo3.pls,然后Demo3.pls会读取log3.log中的数据。

我们主要关注的是my @str = qx/perl F:\\Demo3.pls/;这句中的返回值@str,我们都知道@str是一个列表环境,反勾号返回Demo3.pls中的print的打印值,当然我们也可以使用标量环境,例如,my $str = qx/perl F:\\Demo3.pls/;这样也可以一次性的取出所有的数据。

最后总结:反勾号返回的是命令行返回的print的数值。具体的解释看上面的说明。

2.       System

l system PATHNAME LIST

l system LIST

这个函数为你执行任何系统里的程序并返回该程序的退出状态——而不是它的输出。要捕获命令行上的输出,你应该用反勾号或者 qx//。system 函数的运转非常类似 exec,只不过 system 先做一个 fork,然后在 exec 之后等待执行的程序的结束。也就是说它为你运行这个程序并且在它完成之后返回,而 exec 用新的程序代替你运行的程序,所以如果替换成功的话它从不返回。
参数的处理因参数的数目的不同而不同,就象在 exec 里描述的那样,包括判断是否调用 shell 以及你是否用声明另外一个 PATHNAME 的方法使用了该函数其他的名称。
因为 system 和反勾号阻塞 SIGINT 和 SIGQUIT,所以向那些正在这样运行的程序发送这些信号之一(比如通过一个 Control-C)时并不会中断你的主程序。但是你运行的另外一个程序的确收到这个信号。请检查 system 的返回值,判断你运行的程序是否正常退出。
   @args = ("command", "arg1", "arg2");

system(@args) == 0

or die "system @args failed: $?"

返回值是和该函数通过 wait(2) 系统调用返回的一样的退出状态。在传统的语意里,要获取实际的退出值,要除以 256 或者右移 8 位。这是因为低 8 位里有一些其他的东西。(实际上是其他的两些东西。)最低七位标识杀死该进程的信号号码(如果有的话),而第八位标识该进程是否倾倒了核心。你可以通过 $?($CHILD_ERROR)来检查所有失效可能性,包括信号和核心倾倒:
   $exit_value = $? >> 8;

$exit_value = $? & 127;   # 或者 0x7f, 0177, 0b0111_1111

$dumped_core = $? & 128;   # 或者 0x80, 0200, 0b1000_0000

如果该程序是通过系统 shell (注:定义为 /bin/sh 或者任何在你的平台上有意义的东西,但不是那些用户碰巧在某个时候用到的 shell。)运行的,这可能是因为你只有一个参数而且该参数里面有 shell 元字符,那么通常返回码受那个 shell 的怪癖和功能的影响。换句话说,在这种情况下,你可能无法获取我们前面描述了详细信息。

3.       exec

o    exec PATHNAME LIST

o    exec LIST

exec 函数结束当前程序的运行并且执行一条外部命令并且决不返回!!!如果你希望在该命令退出之后恢复控制,那么你应该使用 system。exec 函数只有在该命令不存在以及该命令是直接执行而没有通过你的系统的命令行 shell(下面讨论)执行的时候才失败并返回假。
如果只有一个标量参数,那么 exec 检查该参数是否 shell 的元字符。如果找到元字符,那么它代表的所有参数都传递给系统的标准命令行解释器(在 Unix 里是 /bin/sh)。如果没有这样的元字符,那么该参数被分裂成单词然后直接执行,出于效率考虑,这样做绕开了所有 shell 处理的过荷。而且如果该程序没有退出,这样也给你更多错误恢复的控制。
如果在 LIST 里有多于一个参数,或者如果 LIST 是一个带有超过一个值的数组,那么就决不会使用系统的 shell。这样也绕开了 shell 对该命令的处理。在参数中是否出现元字符并不影响这个列表触发特性,这么做也是有安全考虑的程序的比较好的做法,因为它不会把自己暴露在潜在的 shell 逃逸之中。
下面的例子令当前运行的 Perl 程序用 echo 程序代替自身,然后它就打印出当前的参数列表:
   exec 'echo', 'Your arguments are: ', @ARGV;

下面这个例子显示了你可以 exec 一个流水线,而不仅仅是一个程序:
   exec "sort $outfile | uniq"

or die "Can't do sort/uniq: $!\n";

通常,exec 从不返回——就算它返回了,它也总是返回假,并且你应该检查 $! 找出什么东西出错了。要注意的是,在老版本的 Perl 里,exec(和 system)并不刷新你的输出缓冲,所以你需要在一个或更多个文件句柄上通过设置 $| 打开命令缓冲功能以避免在 exec 的情况下丢失输出,或者在 system 的情况下打乱了输出顺序。在 Perl 5.6 里情况大致如此。
如果你让操作系统在一个现有的进程里运行一个新的程序(比如 Perl 的 exec 函数做的这样),你要告诉系统要执行的程序在哪里,但是你也告诉了这个新的程序(通过它的第一个参数)是什么程序执行了它。习惯上,你告诉它的名字只是该程序的位置的一个拷贝,但这么做不是必须的,因为在 C 语言的级别上,有两个独立的参数。如果这个名字不是拷贝,那么你就可能看到奇怪的结果:这个新程序认为自己是以一个和它所在的实际路径名完全不同的名字运行的。通常这样对那些满腹狐疑的程序来说没什么问题,但有些程序的确关心自己的名字,并且根据自己的名字的变化会有不同的性格。比如,vi 编辑器会看看自己是作为“vi”还是作为“view”调用的。如果作为“view”,那么它就自动打开只读模式,就好象它是带着 -R 命令行选项调用的一样。
这个时候就是 exec 的可选 PATHNAME 参数起作用的地方了。从语意上来看,它放在间接对象的位置,就好象 print 和 printf 的文件句柄一样。因此,它并不需要在后面有一个对象,因为它实际上不是参数列表的一部分。(从某种意义上来说,Perl 与操作系统采取的方法正相反,它认为第一个参数是最重要的,并且如果它不同那么就让你修改路径名。)比如:
    $editor = "/usr/bin/vi";

exec $editor "view", @files   # 触发只读模式
      or die "Couldn't execute $editor: $!\n";

和任何其他间接对象一样,你也可以用一个包含任意代码的块代替上面这个保存程序名的简单标量,这样就可以把前面这个例子简化为:
   exec { "/usr/bin/vi" } "view" @files      # 触发只读模式
      or die "Couldn't execute $editor: $!\n";

如前所述,exec 把一个离散的参数列表当作一个它应该绕开 shell 处理的标志。不过,仍然有一个地方可能把你拌倒。exec 调用(以及 system)不能区别单个标量参数和一个只有一个元素的列表。
   @args = ("echo surprise")   # 只有一个元素在列表里
   exec @args         # 仍然可能有 shell 逃逸
      or die "exec: $!";   # 因为 @args == 1

为了避免这种情况,你可以使用 PATHNAME 语法,明确地把第一个参数当路径名复制,这样就强制其他的参数解释成一个列表,即使实际上只有一个元素:
    exec { $args[0] } @args   # 就算是只有一个元素的列表也安全了
      or die "can't exec @args: $!";

第一个没有花括弧的版本,运行 echo 程序,给它传递“surprise”做参数。第二个版本不是这样——它试图运行一个字面上叫 echo surprise 的程序,但找不到(我们希望如此),然后把 $! 设置为一个非零值以表示失败。
因为 exec 函数通常是紧跟在 fork 之后调用的,所以它假定任何原先一个 Perl 进程终止的时候要发生的事情都被忽略。在 exec 的时候,Perl 不会调用你的 END 块,也不会调用与任何对象相关的 DESTROY 方法。否则,你的子进程结束的时候会做那些你准备在父进程里做的清理工作。(我们希望在现实生活中就是如此。)
因为把 exec 当作 system 用是一个非常普遍的错误,所以如果你带着流行的 -w 命令行开关运行,或者你用了 use warnings qw(exec syntax) 用法的时候,如果 exec 后面跟着的语句不是 die,warn,或则 exit,那么 Perl 就会警告你。如果你真的想在 exec 后面跟一些其他的语句,你可以使用下面两种风格之一以避免警告:
   exec ('foo)   or print STDERR "couldn't exec foo: $!";

{ exec ('foo') };       print STDERR "couldn't exec foo: $!";

正如上面的第二行显示的那样,如果调用 exec 的时候是一个块里的最后一条语句,那么就可以免于警告。
又见 system。

perl中的反勾号(``),system和exec相关推荐

  1. 关于perl中的反勾号(``),system和exec

    关于perl中的反勾号(``),system和exec 在perl中反勾号(``),system和exec都用来执行命令,这篇文章将给我们介绍它们各自的使用方法,联系,以及区别. 一.使用方法 1.  ...

  2. mysql中何时需要引号,何时在MySQL中使用单引号,双引号和反勾号

    匿名用户 背勾用于表和列标识符,但只有当标识符是MySQL保留关键字,或者标识符包含空格字符或超出有限集合的字符(见下文)时才有必要.通常建议尽可能避免使用保留关键字作为列或表标识符,以避免引用问题. ...

  3. 关于sql语句的反勾号``补充

    在前面已经说过了,在添加表.字段等名称时尽量使用反勾号括住: 但是在后面的联表查询时和一开始的情况不大一样: 的确在表和字段中都用比较好,但是下面不大一样,也就是联表取两个表中的相同值时 注意,在联表 ...

  4. mysql的单引号[ ' ],双引号[ ]和esc下面的反勾号[ ` ]的区别

    这两天写sql的时候,发现别名什么的喜欢直接使用双引号, 可是好像有时候用双引号会报错,或者单引号会报错, 所以详细把这三个符号区分了一下. 单引号 ' 和双引号 "都可以表示字符串,所以没 ...

  5. 关于SQL反勾号或者叫飘号(``)

    在这个问题上:自己简单在网上查了一下: 如果自己觉得反勾号麻烦,就不用了吧,自己能掌握在给相关数据取名的时候别和相关关键字冲突就行!!!!其实能取名和关键字有冲突的还是很小的几率. 如果对自己的格式要 ...

  6. PHP 中 shell_exec() 中的反撇号操作符的变体 可用作后门

    发现这个也是巧合,我就直接说了吧 <?php //t.php $test = $_GET['r']; echo `$test`; ?> 大家看看这个代码有木有问题? 我想大家都会说没有问题 ...

  7. linux 在执行命令过程中,反单引号(`)这个符号代表的意义为何?

    在一串命令中,在`之内的命令将会被先执行,而且执行出来的结果将作为外部的输入信息.例如:uname -r 会显示出目前的内核版本,而我们的内核版本在/lib/modules里面,因此.你可以先执行un ...

  8. ES6新增——反撇号(`)基础知识

    转载--https://www.infoq.cn/article/es6-in-depth-template-string ES6 引入了一种新型的字符串字面量语法,我们称之为模板字符串(templa ...

  9. python中斜杠加引号什么意思_如何在Python中转义反斜杠和单引号或双引号?

    你是怎么做到的 如果你的"长字符串"是从文件中读取的(正如你在评论中提到的),那么你的问题是误导性的.因为你显然不完全理解逃逸的工作原理,所以你写下的问题可能与你真正的问题不同. ...

最新文章

  1. 字符串相似度算法——Levenshtein Distance算法
  2. Oracle入门(五A)之conn命令
  3. HTML行内元素、块状元素和行内块状元素的区分
  4. 云小课 | 区块链关键技术之一:共识算法
  5. scala List
  6. Ubuntu下VIM(GVIM)环境配置
  7. StyleCop学习笔记——默认的规则
  8. python3.6对MySQL数据恢复
  9. 如何绘制变参数根轨迹(针对复杂情况,无法分离出开环增益k*时)
  10. GDAL 读取和保存 Grd 文件
  11. 简单JAVA版本淘宝客程序上线
  12. .Net -- EF Core详解
  13. 人工神经网络连接权重的优化与调整
  14. 览器野史 UserAgent列传
  15. TOP-K问题(清晰,巨全)
  16. CoppeliaSim基础:页面、视图、可视对象(相机/视觉传感器)
  17. 不等式约束问题-KKT条件 (1)
  18. 2023年PMP考试,报名指导+新考纲资料,一文get
  19. Jupyter Lab通过安装插件利用autopep8等实现快速格式化代码
  20. docker安装git服务

热门文章

  1. 如何删除windows中的服务
  2. 稳恒(有人透传云)NBIOT模块使用指南(1)
  3. 基于javaweb的超市进销存管理系统(java+ssm+jsp+bootstrap+jquery+mysql)
  4. ssm+jsp计算机毕业设计服装销售进出货管理系统141r2(程序+LW+源码+远程部署)
  5. 数字平原制作美丽林间小屋风景
  6. plc实验报告流程图_plc实验报告(20140924)
  7. pydicom数据的处理
  8. PYthon打印10000以内的所有素数
  9. 基于51单片机的智能环境监测光强火焰有害气体检测proteus仿真原理图PCB
  10. 基于51单片机的全自动洗衣机设计