捕获Perl系统的输出()

Dag*_*ang 26 shell perl

我需要在Perl中使用system()运行shell命令.例如,

system('ls')

系统调用将打印到STDOUT,但我想将输出捕获到变量中,以便我可以使用Perl代码进行将来的处理.

Zai*_*aid 44

这就是反叛的目的.来自perldoc perlfaq8:

为什么我不能得到命令的输出system()

你混淆system()和反叛的目的(``).system() 运行命令并返回退出状态信息(作为16位值:低7位是进程死亡的信号,如果有的话,高8位是实际退出值).反引号(``)运行命令并返回它发送给STDOUT的内容.

my $exit_status   = system("mail-users");
my $output_string = `ls`;
Run Code Online (Sandbox Code Playgroud)

有关perldoc perlop详细信息,请参阅

  • 实际上,我认为提出这个问题是有效的:“system()”在将参数作为数组传递时(在“不安全”参数的情况下)具有其他替代方案所没有的优势(据我所知)。 (2认同)

Leo*_*erd 17

IPC::Run这是我最喜欢的这类任务的模块.非常强大和灵活,对于小案例也非常简单.

use IPC::Run 'run';

run [ "command", "arguments", "here" ], ">", \my $stdout;

# Now $stdout contains output
Run Code Online (Sandbox Code Playgroud)

  • 我一直在寻找一种简单的方法来传递没有shell插值的命令参数,并从所谓的命令中捕获stdout.很好的答案,谢谢! (3认同)

Zni*_*nik 7

只需使用类似于bash的例子:

    $variable=`some_command some args`;
Run Code Online (Sandbox Code Playgroud)

就这样.注意,您不会在输出上看到任何打印到STDOUT,因为它被重定向到变量.除了准备好的答案之外,此示例对于与用户交互的命令无法使用.为此你可以使用一堆shell命令来使用这样的东西:

    $variable=`cat answers.txt|some_command some args`;
Run Code Online (Sandbox Code Playgroud)

在answers.txt文件中你应该准备some_command的所有答案正常工作.

我知道这不是最好的编程方式:)但这是如何实现目标的最简单方法,特别是对于bash程序员.

当然,如果输出更大(带子目录的ls),则不应立即获得所有输出.通过与读取regullar文件相同的方式读取命令:

open CMD,'-|','your_command some args' or die $@;
my $line;
while (defined($line=<CMD>)) {
    print $line; #or push @table,$line or do whatewer what you want processing line by line
}
close CMD;
Run Code Online (Sandbox Code Playgroud)

用于处理长命令输出而无需额外bash调用的附加扩展解决方案:

my @CommandCall=qw(find / -type d); #some example single command
my $commandSTDOUT; #file handler
my $pid=open($commandSTDOUT),'-|'); #there will be implict fork!
if ($pid) {
    #parent side
    my $singleLine;
    while(defined($singleline=<$commandSTDOUT>)) {
        chomp $line; #typically we don't need EOL
        do_some_processing_with($line);
    };
    close $commandSTDOUT; #in this place $? will be set for capture
    $exitcode=$? >> 8;
    do_something_with_exit_code($exitcode);
} else {
    #child side, there you really calls a command
    open STDERR, '>>&', 'STDOUT'; #redirect stderr to stdout if needed, it works only for child, remember about fork
    exec(@CommandCall); #at this point child code is overloaded by external command with parameters
    die "Cannot call @CommandCall"; #error procedure if call will fail
}
Run Code Online (Sandbox Code Playgroud)

如果你使用这样的程序,你将捕获所有程序输出,你可以逐行处理所有事情.祝好运 :)