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

Hello Monks, I want to send an output of a Unix command, say "ls", to my Perl program, say "a.pl". How should "a.pl" look like if I want it to have $var which will contain the output of "ls" ? Thanks !

Replies are listed 'Best First'.
Re: Need help with Piping
by lidden (Curate) on Aug 13, 2008 at 05:56 UTC
    #!/usr/bin/perl -w use strict; my $var = ''; while(<>){ $var .= $_; } # Do stuff with $var

      If I just want the STDIN (or any file content) in a variable, and don't like to loop, I usually use this idiom:

      my $var; SLURP: { local $/; $var= <>; }

      local-izing $/ in a block undefines it and so no $var gets the whole filecontent sithout looping and reassembling it line by line.


      s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
      +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
        I like Skeeve's solution. It is the best and clearest way to do this in Perl 5.

        For the sake of completeness: In Perl 6 the built-in way for this is simply:

        $var = slurp \*STDIN;

        This can also be done in Perl 5 by using the Perl6::Slurp module.

        You can do all of that in one line...

        my $var = do { local $/ ; <> };

        www.jasonkohles.com
        We're not surrounded, we're in a target-rich environment!
Re: Need help with Piping
by Bloodnok (Vicar) on Aug 13, 2008 at 10:39 UTC
    Using a one-liner and backticks, perl -e '{ .... }' `ls -l`, @ARGV will be loaded with the output from the ls command.

    However, if you wanted to process each line in turn, you could use a one-liner ... ls -l | perl -ne '{ .... }' to read each line of the ls command, in turn, into $_ or alternatively ... ls -l | perl -ane '{ .... }' will read each line in turn and split it (the line) on whitespace, into @F.

    HTH ,

    A user level that continues to overstate my experience :-))
Re: Need help with Piping
by eosbuddy (Scribe) on Aug 13, 2008 at 05:43 UTC
    a.pl is as below:
    use strict; use warnings; print "$_\n" while (<>);
    Update (multiple): apologies, didn't see the  $var part. I assume, you are going to use it as a list:
    my @var; push(@var, $_) while(<>);
      I forgot to mention that you will need to  chomp depending on the situation (e.g. ls adds a "\n" automatically when piped while other commands may not behave in a similar manner).
Re: Need help with Piping
by zentara (Cardinal) on Aug 13, 2008 at 16:14 UTC
    You have some solutions for getting STDIN, but do you really need separate scripts? Why not let a.pl run 'ls' or your command? Trying to force things thru STDIN is often frought with difficulty and should be avoided if possible, unless you need to build a chain of commands for some reason.

    Just use a piped open, or read perldoc perlipc for the many other ways to do it.

    #!/usr/bin/perl open (LS,"ls |" ) or die $!; my @files = (); while(<LS>){ chomp; push @files, $_; } print "@files\n";

    I'm not really a human, but I play one on earth Remember How Lucky You Are
Re: Need help with Piping
by blazar (Canon) on Aug 14, 2008 at 17:10 UTC

    I personally believe that quite a full overview of all the possibilities has already been offered to you. But there's a last one missing, that I'm reporting here FYI and for completeness: the implicit open associated with the magic ARGV filehandle is the 2-args one. (Which incidentally I regard as problematic in many senses...) Thus you can pass commands to your script on the command line:

    spock:~ [18:59:27]$ perl -0777e 'my $v = <>; print $v' 'ls|' Desktop Mail Mailbox bin dead.letter ...
    --
    If you can't understand the incipit, then please check the IPB Campaign.