【问题标题】:Perl: STDOUT/the output of shell command to an array directlyPerl:STDOUT/shell命令直接输出到数组
【发布时间】:2015-12-11 03:07:48
【问题描述】:

我必须访问一个 shell 命令 - Perl 脚本中的 hive,所以我使用 `...`。 假设 `hive ... ...` 的结果包含 100000000 行,大小为 20GB。 我想要达到的效果是这样的:

@array = `hive ... ...`;

`` 是否自动知道使用“\n”作为分隔符将每一行划分为@array?

我能想到的两种方法是(但在这种情况下有问题):

$temp = `hive ... ...`;
@array = split ( "\n", $temp );
undef $temp;

这种方式的问题是,这种情况下如果hive的输出太大,$temp无法存储输出,导致segmentation fault core dump。

`hive ... ... 1>temp.txt`;
open ( FP, <, "temp.txt" );
while (<FP>)
{
    chomp;
    push @array, $_;
}
close FP;
`rm temp.txt`;

但是这种方式太慢了,因为它首先将结果写入硬盘。

有没有办法在不使用任何“临时容器”的情况下将 shell 命令的输出直接写入数组?

非常感谢您的帮助。

【问题讨论】:

    标签: arrays perl shell system stdout


    【解决方案1】:
    @array = `command`;
    

    实际上,将command 的每一行输出放入它自己的@array 元素中。无需自己将输出加载到标量和split 中。

    但是 20GB 的输出存储在一个数组中(由于 Perl 存储数据的方式,可能是这个数量的 2-3 倍)仍然会给您的系统带来巨大的压力。

    解决问题的真正方法是通过 IO 句柄流式传输命令的输出,一次处理一行,而不必一次将所有输出加载到内存中。方法是使用 Perl 的 open 命令:

    open my $fh, "-|", "command";
    open my $fh, "command |";
    

    附加到命令的-| 文件模式或| 告诉Perl 运行外部命令,并使该命令的输出在文件句柄$fh 中可用。

    现在迭代文件句柄以一次接收一行输出。

    while (<$fh>) {
        # one line of output is now in $_
        do_something($_);
    }
    close $fh;
    

    【讨论】:

    • 非常感谢。我试过你的方法。只是担心高内存消耗并将20gb放入ram仍然很慢。这种方式非常棒,速度快,内存使用率低。
    猜你喜欢
    • 2015-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-18
    • 2023-03-26
    • 1970-01-01
    • 2013-06-08
    • 2019-01-30
    相关资源
    最近更新 更多