http://qs321.pair.com?node_id=339092

When you have program data that must be fed as the standard input to a process, and you want to capture its output, and you want to avoid the shell, it's time for a double fork!
my @INPUT = (... many lines of text ...); my @COMMAND = qw(tr a-zA-Z A-Za-z); # swap lower/upper case my @RESULT; # this is where the result will go... if (open RESULT, "-|") { # original process @RESULT = <RESULT>; } else { # child if (open STDIN, "-|") { # child exec @COMMAND; die "Cannot exec: $!"; } else { # grandchild print @INPUT; exit 0; } }

Replies are listed 'Best First'.
Re: feeding text to a process, and capturing its output, safely
by QM (Parson) on Mar 23, 2004 at 19:49 UTC
    Can you comment on the "safely" aspect of this?

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of

      Yes.

      Oh, you mean will I elaborate?

      OK.

      No shell is involved. This makes it safer than the solutions I've seen that usually end up as something like:

      my @RESULT = `echo $INPUT | Some Command`;
      The problem is that $INPUT is being handed to a shell, making me have to worry and wonder about all shell-sensitive characters.

      -- Randal L. Schwartz, Perl hacker
      Be sure to read my standard disclaimer if this is a reply.

        Thanks, I had forgotten about that.

        I should think this method might be preferred then, unless the application is something quick-and-dirty.

        Will you please comment on the disadvantages of this method?

        -QM
        --
        Quantum Mechanics: The dreams stuff is made of

Re: feeding text to a process, and capturing its output, safely
by duelafn (Parson) on Jun 09, 2011 at 16:10 UTC

    Converted to a subroutine, make the exec safer, optionally capture STDERR, lexical filehandle:

    =head3 safe_pipe safe_pipe [ options, ] command, input my $results = safe_pipe [ 'command', 'arg' ], @input; my @results = safe_pipe [ 'command', 'arg' ], @input; my $results = safe_pipe { capture_err => 1 }, [ 'command', 'arg' ], @ +input; Pipe data to a shell command safely (without touching a command line) +and retrieve the results. Options: =over 4 =item capture_err If true, STDERR will also be captured and included in returned results +. =back =cut sub safe_pipe { my $opt = {}; $opt = shift if 'HASH' eq ref($_[0]); my $command = shift; my ($RESULT, @x); $command = [$command] unless ref $command; if (open $RESULT, "-|") { # original process: receiver (reads $RESUL +T) @x = <$RESULT>; } else { if (open STDIN, "-|") { # child: processor (reads STDIN, writes ST +DOUT) open STDERR, ">&STDOUT" or die "Can't dup STDOUT: $!" if $$opt{c +apture_err}; exec { $$command[0] } @$command; die "Cannot exec @$command: $!"; } else { # grandchild: sender (writes STDOUT) print @_; exit 0; } } wantarray ? @x : join('', @x); }

    Good Day,
        Dean

Re: feeding text to a process, and capturing its output, safely
by Anonymous Monk on Mar 24, 2004 at 07:50 UTC

    Do you have a Win32 version of this as well?