Perl的system()如何打印它正在运行的命令?

时间:2008-08-19 23:47:01

标签: perl system

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

通常情况下这很有用,但有时候我想知道幕后发生了什么。如何将所执行的命令打印到终端,并将这些程序的输出打印到终端?这将是{@ 1}}相当于“@echo on”。

6 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

等...

更新:如果你想打印命令的名称是system(),我认为Rudd的方法很好。在此重复进行整合:

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

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

答案 2 :(得分:5)

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

open(LS,"|ls");
print LS;

答案 3 :(得分:4)

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

sub execute {
  my $cmd = shift;
  print "$cmd\n";
  my $ret = `$cmd`;
  print $ret;
  return $ret;
}

答案 4 :(得分:2)

嗯,有趣的是,不同的人如何回答这些不同的方式。在我看来,mkDaniel Fone将其解释为想要查看/操纵命令的标准输出(他们的解决方案都没有捕获stderr fwiw)。我认为Rudd越来越近了。你可以对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"};
    }
  }

答案 5 :(得分:1)

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

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

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