Grundle has asked for the wisdom of the Perl Monks concerning the following question:

I was wondering if there is a way to get the system output from a system call to be "piped" back into a perl variable. If you do something like

$var = system "some system call";

it will merely return whether or not the system call was successful (i.e. a status number.) I was hoping I could magically read the output back into a variable instead of piping the output to a file and then reading the file like so

$var = system "some system call > some_file.extension"; if($var){ #open file and parse the contents into a string }

Replies are listed 'Best First'.
Re: Read System output Into a variable Name?
by brian_d_foy (Abbot) on Feb 01, 2005 at 20:08 UTC

    Other monks have already mentioned the backticks and qx() operators, which are explained in the "Quote and Quote-like Operators" section of the perlop man page.

    The perlipc man page talks about all sorts of different ways to do things, and the IPC::Open2 and IPC::Open3 modules are good too.

    If you want the data back as one chunk, the backticks probably are what you want. If you can do things line by line, or the external process outputs lines slowly, you probably want open() with a pipe. If you have to deal with STDERR too, and maybe write something to the process, you probably want one of the IPC:: modules (some programs seem to want me to close their STDIN before they write anything). Figure out which one works for your situation, and good luck :)

    --
    brian d foy <bdfoy@cpan.org>
      This is a good explanation in helping me determine what I needed to use. It turns out that all I need is to store the entire output as a string without worrying about lines, or even formatting conventions.

      Thank you to everyone who contributed. I especially enjoyed reading about the differences between the backticking and open() with pipes. I know I will use both in the future.
Re: Read System output Into a variable Name?
by fglock (Vicar) on Feb 01, 2005 at 19:26 UTC
      Backticks are less efficient than using open() and |. For one thing, backticks have to read the whole result into memory at once. For another, having the second process running while you're dealing with the input allows the scheduler to be more efficient.

      Additionally, backticks interpolate, which can cause issues with set-id scripts. Pipes get around this.

      Being right, does not endow the right to be rude; politeness costs nothing.
      Being unknowing, is not the same as being stupid.
      Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
      Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

        For the latter issue, regarding interpolation of the command string itself, see qx// with single-quotes.
        $output = qx' command @which $should not be interpolated ';

        --
        [ e d @ h a l l e y . c c ]

Re: Read System output Into a variable Name?
by dragonchild (Archbishop) on Feb 01, 2005 at 19:23 UTC
    open( SOME_PIPE, "some command -|" ) or die "Cannot open pipe: $!\n"; my @output = <SOME_PIPE>; close SOME_PIPE;

    Being right, does not endow the right to be rude; politeness costs nothing.
    Being unknowing, is not the same as being stupid.
    Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
    Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

      using open() is a quick easy way of doing it. But working with external files slows down any script. I would suggest using backticks, and then parsing out the data you want using regex and/or split. I had a script which was taking 15 minutes to run when it was using external files. I optimized it using split -- and now it only takes 8 minutes. But as the perl slogan goes: There is more than one way to do it.

      - Justin
        I'm not quite sure I understand where you're going here. The use of backticks is essentially a wrapper around open("-|"). The only difference is that you're using the OS to buffer your data as opposed to pulling it all into your process memory. If the output from the external process is large, you can easily start paging your process's memory. If you treat it as a socket (which, in essence, it is), you can bring the results in as you need, keeping only the data you want.

        Unless, of course, you thought I was using system(), redirecting the results to a temp file, then open()'ing the temp file ... that's not what I was suggesting. Please read the documentation for open and look for the section dealing with -|.

        Being right, does not endow the right to be rude; politeness costs nothing.
        Being unknowing, is not the same as being stupid.
        Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
        Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

Re: Read System output Into a variable Name?
by borisz (Canon) on Feb 01, 2005 at 19:27 UTC
    use backticks or qx;
    my $var = `system_command`;
    or
    my $var = qx/system_command/;
    Boris
Re: Read System output Into a variable Name?
by ikegami (Patriarch) on Feb 01, 2005 at 19:27 UTC