Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Another Q about piping Perl

by Elvis (Sexton)
on Oct 12, 2001 at 03:04 UTC ( [id://118363]=perlquestion: print w/replies, xml ) Need Help??

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

Hi,
Just for fun, I'd like to use perl instead of sed on the following line:

echo $HOME/Mail/* |sed 's/sent-mail //

So far, I've tried various things that leave me with no output or wrong output. E.g:

echo $HOME/Mail/* | perl -e 'while (<STDIN>=~s/sent-mail//) { print " +$_"}'

I've had a look at the Capturing input from pipe? node, but I'm still clueless. I've also used the s2p (sed2perl) program, but the output seems far from succint. I thought perl would be able to do the same task in as short a line as the sed command. Can it?

I'm very much a perl novice (initiate even), and would really appretiate your help.

Thank You.

Replies are listed 'Best First'.
Re: Another Q about piping Perl
by stefp (Vicar) on Oct 12, 2001 at 03:18 UTC
    The idiom to execute perl statements on and print the result of each line of a file is
    perl -pe 'perl_statements' < file
    or
    some_command | perl -pe 'perl_statements'

    each line is stored in $_ on which perl_statements act.

    Here you want to print all the files in the $HOME/Mail directory. An all perl solution is:
       map{ -f  $_  and print "$_ " } <$ENV{HOME}/MAIL/*>

    Some people consider using map on empty context is bad form. I don't. They would propose instead:   for(<$ENV{HOME}/MAIL/*>) {  -f  $_  and print "$_ " }
    or
      -f  $_  and print "$_ " for  <$ENV{HOME}/MAIL/*>

    TMTOWTDI

    -- stefp

      stefp wrote:

      Some people consider using map on empty context is bad form. I don't.

      I think it depends on the context. If you're doing a short one-liner like that, it's not a big deal. In fact, if you're just writing a small "throw away" script that only gets used once or twice and you don't care about performance or memory, then it's not a big deal IMHO. However, if you're writing large applications, it pays to be rigorous. Creating a bunch of only to throw away the return value is a waste of resources and a for loop is preferable. Doing what you did to print all the files in the $HOME/MAIL/ directory:

      # print all files in the directory (an overblown and limited 'ls' +or 'dir' perl -e '-f $_ and print "$_ " for glob(shift)' ./*

      Side note: since I tested that on a Windows box and it doesn't like single quotes on the command line and I hate using \" all the time to embed quotes, I wrote this:

      perl -e "-f $_ and print $_.$,.$/ for glob(shift)" ./*

      No wonder people say Perl has too much punctuation :)

      Cheers,
      Ovid

      Update: Hmm... seems I wasn't paying attention to blakem's post.

      Vote for paco!

      Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      I like map as much as the next guy (see the "extended" Location field on my homenode) but why not write the above map as:
      -f $_ && print "$_ " for <$ENV{HOME}/MAIL/*>

      -Blake

Re: Another Q about piping Perl
by tommyw (Hermit) on Oct 12, 2001 at 03:20 UTC

    Well, the error message about being unable to modify <HANDLE> might be considered a bit of a clue: grab the input, and modify it separately:

    echo $HOME/Mail/* | perl -e 'while (<STDIN>) { s/sent-mail//; print "$ +_"}'

    Or just use the -p option, and really make it look like your sed command:

    echo $HOME/Mail/* | perl -p -e '/sent-mail//'

    update:Whoops. Of course, the missing s before the substitution string was meant as an exercise for the reader ;) echo $HOME/Mail/* | perl -p -e 's/sent-mail//'

    But personally, I'd stick with sed, if I've got the choice: it's less memory hungry for such simple tasks

Re: Another Q about piping Perl
by thatguy (Parson) on Oct 12, 2001 at 03:20 UTC
    I am not sure if you are trying to exclude the sent-mail folder or what.. if you are just pulling out the phrase 'sent-mail' (which will pull it out of even recieved mail) then this will work:
    echo $HOME/Mail/* | perl -e 'while(<>){$_=~ s/sent-mail//;if($_){print}}'

    if you just want the received mail, then you are better off with this:

    echo $HOME/Mail/received | perl -e 'print <>'
    -p

Re: Another Q about piping Perl
by chazzz (Pilgrim) on Oct 12, 2001 at 13:53 UTC
    Here's my take on this...

    perl -e "while(<>){s/sent-mail //;print;}"

    Short and sweet :)
(tye)Re: Another Q about piping Perl
by tye (Sage) on Oct 12, 2001 at 19:50 UTC

    Several replies mention "-pe" but the default behavior of 'sed' is actually best duplicated with "-ne": echo $HOME/Mail/* | perl -ne "print if s/sent-mail //"

            - tye (but my friends call me "Tye")
Re: Another Q about piping Perl
by Elvis (Sexton) on Oct 12, 2001 at 21:23 UTC

    Thanks for the excellent replies.

    FWIW, I'm trying to exculde my sent-mail folder from the listing. It's to do with my .muttrc file.

    I'm not too sure I understand the map function well, but it made interesting reading. Also in future, I'm going to have to take more notice of the perl --help output. :)

    Thanks Again.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://118363]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (6)
As of 2025-06-16 15:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.