Perl的system()如何打印正在运行的命令?
时间:2020-03-05 18:40:57 来源:igfitidea点击:
在Perl中,我们可以使用system()或者``(反引号)执行系统命令。我们甚至可以将命令的输出捕获到变量中。但是,这会将程序执行隐藏在后台,以便执行脚本的人看不到它。
通常,这很有用,但有时我想看看幕后发生了什么。我们如何做到这一点,以便将执行的命令打印到终端上,并将那些程序的输出打印到终端上?这相当于" @bat on"的" .bat"。
解决方案
回答
请改用open。然后,我们可以捕获命令的输出。
open(LS,"|ls"); print LS;
回答
据我了解,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()命名的命令的名称,我认为陆克文的方法很好。在此处重复进行合并:
sub execute { my $cmd = shift; print "$cmd\n"; system($cmd); } my $cmd = $ARGV[0]; execute($cmd);
回答
我不知道执行此操作的任何默认方法,但是我们可以定义一个子例程来为我们执行此操作:
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
回答
嗯,很有趣,不同的人如何以不同的方式回答。在我看来,就像mk一样,Daniel Fone将其解释为希望查看/操纵命令的标准输出(他们的解决方案均未捕获stderr 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"}; } }
回答
与答案中提到的其他技术结合的另一种技术是使用" tee"命令。例如:
open(F, "ls | tee /dev/tty |"); while (<F>) { print length($_), "\n"; } close(F);
这将打印出当前目录中的文件(由于使用tee / dev / tty),还打印出每个读取的文件名的长度。
回答
这是更新的执行,将打印结果并返回它们:
sub execute { my $cmd = shift; print "$cmd\n"; my $ret = `$cmd`; print $ret; return $ret; }