12

在 Perl 中,您可以使用 system() 或 ``(反引号)来执行系统命令。您甚至可以将命令的输出捕获到变量中。但是,这会在后台隐藏程序执行,因此执行脚本的人看不到它。

通常这很有用,但有时我想看看幕后发生了什么。您是如何做到的,以便将执行的命令打印到终端,并将这些程序的输出打印到终端?这.bat相当于“@echo on”。

4

6 回答 6

19

我不知道执行此操作的任何默认方法,但您可以定义一个子例程来为您执行此操作:

sub execute {
    my $cmd = shift;
    print "$cmd\n";
    system($cmd);
}

my $cmd = $ARGV[0];
execute($cmd);

然后看看它的实际效果:

pbook:~/foo rudd$ perl foo.pl ls
ls
file1   file2   foo.pl
于 2008-08-20T01:47:02.190 回答
10

据我了解, system() 将打印命令的结果,但不会分配它。例如。

[daniel@tux /]$ perl -e '$ls = system("ls"); print "Result: $ls\n"'
bin   dev  home  lost+found  misc  net  proc  sbin     srv  System  tools  var
boot  etc  lib   media       mnt   opt  root  selinux  sys  tmp     usr
Result: 0

反引号将捕获命令的输出而不打印它:

[daniel@tux /]$ perl -e '$ls = `ls`; print "Result: $ls\n"'
Result: bin
boot
dev
etc
home
lib

ETC...

更新:如果您还想打印正在执行的命令的名称system(),我认为Rudd的方法很好。在此重复以进行合并:

sub execute {
    my $cmd = shift;
    print "$cmd\n";
    system($cmd);
}

my $cmd = $ARGV[0];
execute($cmd);
于 2008-08-20T01:30:36.597 回答
5

改用 open 。然后您可以捕获命令的输出。

open(LS,"|ls");
print LS;
于 2008-08-20T00:04:56.210 回答
5

这是一个更新的执行,它将打印结果并返回它们:

sub execute {
  my $cmd = shift;
  print "$cmd\n";
  my $ret = `$cmd`;
  print $ret;
  return $ret;
}
于 2008-08-20T16:33:40.217 回答
2

嗯,有趣的是不同的人如何以不同的方式回答这个问题。在我看来,mkDaniel Fone将其解释为想要查看/操作命令的标准输出(他们的解决方案都没有捕获标准错误 fwiw)。我认为陆克文走得更近了。您可以对 Rudd 的响应做出的一种改变是用您自己的版本覆盖内置的 system() 命令,这样您就不必重写现有代码来使用他的 execute() 命令。

使用 Rudd 帖子中的 execute() 子程序,您可以在代码的顶部有这样的内容:

if ($DEBUG) {
   *{"CORE::GLOBAL::system"} = \&{"main::execute"};
}

我认为这会起作用,但我不得不承认这是伏都教,而且我已经有一段时间没有写这段代码了。这是我几年前编写的代码,用于在模块加载时拦截本地(调用命名空间)或全局级别的系统调用:

  # importing into either the calling or global namespace _must_ be
  # done from import().  Doing it elsewhere will not have desired results.
  delete($opts{handle_system});
  if ($do_system) {
    if ($do_system eq 'local') {
      *{"$callpkg\::system"} = \&{"$_package\::system"};
    } else {
      *{"CORE::GLOBAL::system"} = \&{"$_package\::system"};
    }
  }
于 2008-08-20T02:06:10.490 回答
2

与答案中提到的其他技术相结合的另一种技术是使用该tee命令。例如:

open(F, "ls | tee /dev/tty |");
while (<F>) {
    print length($_), "\n";
}
close(F);

这既会打印出当前目录中的文件(作为 的结果tee /dev/tty),也会打印出读取的每个文件名的长度。

于 2008-08-20T06:33:49.673 回答