Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

'perl -p' ne 'cat'

by grinder (Bishop)
on Jun 03, 2002 at 15:08 UTC ( [id://171252]=perlmeditation: print w/replies, xml ) Need Help??

I was doing some system maintenance, and at some point I had a script that spewed out a series of values, one per line. Rather than running the command again and more(1)ing it, the lightbulb went off over my head (actually it went on, but chalk that up to an inconsistency of the English language). It occurred to me that all I had to do was filter the output by changing newlines to spaces and I'd probably be able to see all the output in a screenful of space.

Armed with my knowledge of Perl's -l (ell) switch, I quickly reran the command as:

an|extremely|long|pipe|perl -pl40

... and was greeted with the rather cryptic

syntax error at - line 62, near "[some output from my command pipe]" Execution of - aborted due to compilation errors.

After fiddling around with things for a while, I realised that I had to:

an|extremely|long|pipe|perl -pl40 -e 1

And all was well. So I thought that I had missed something in the documentation. It sez here (v5.6.0)

-p causes Perl to assume the following loop around your program, which makes it iterate over filename arguments somewhat like sed: LINE: while (<>) { ... # your program goes here } continue { print or die "-p destination: $!\n"; }

Well that's all well and good (and as I remembered). Annoyingly, it's also exactly what I want, but it doesn't really do that. Time to bring out B::Deparse.

% perl -MO=Deparse -pl40 ^D LINE: while (defined($_ = <ARGV>)) { chomp $_; } continue { print $_; } - syntax OK % perl -MO=Deparse -pl40 -e 1 LINE: while (defined($_ = <ARGV>)) { chomp $_; '???'; } continue { print $_; } -e syntax OK

Now I get really confused. The above code, with or without the -e 1 would be just fine. Stripped to its simplest expression, consider the following:

% cat >foo foo bar: ^D % cat foo | perl -p syntax error at - line 2, near "foo bar:" Execution of - aborted due to compilation errors.
</code>

Now I'm beginning to see the light:

% cat >foo print "hello, world\n" ^D % cat foo | perl hello, world

That is, despite the presence of the -p (or -n no doubt as well), perl insists on looking for its code on STDIN. But -p has already supplied the code it needs, so why is it doing that? In other words, if perl -p had the same effect as cat(1), then you could do all sorts of things to the file, simply by playing with -l and -0, and possibly a few more besides.

update: bzzt! Abigail points out the flaw. I don't use -p on the shebang line, only for one-liners. Once it can't fit on the command line, I tend to write things out in full. Using -p in a file strikes me as being unecessarily golfish, but that might be just me. Oh well.


print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u'

Replies are listed 'Best First'.
Re: 'perl -p' ne 'cat'
by Abigail-II (Bishop) on Jun 03, 2002 at 15:32 UTC
    Suppose it wouldn't. Then you would no longer be able to start off a program with
    #!/usr/bin/perl -p
    and execute the file the program is in.

    You do know how the kernel deals with #!, don't you?

    Abigail

      I pondered this on the way home. I know you can use -p on the shebang line, but in that case, the question to ask would be what happens when you run a script that contains

      #! /usr/bin/perl -p

      ... and nothing else. Curiously enough, this does do the same thing as cat(1). Which only begs the question why does it work when -p is placed on the shebang line of a script, as opposed to needing -e 1 when used on a command line? The command line behaviour looks like a bug to me.


      print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u'
        Which only begs the question why does it work when -p is placed on the shebang line of a script, as opposed to needing -e 1 when used on a command line?

        For the same reason you *never* need -e if you run the program from a file - either by using the shebang line, or by doing perl program.

        Perl uses the following strategy to find the program:

        1. If there are one or more -e arguments, that's where the program was found.
        2. If the command was invoked as perl [options] file, the program text is found in the file.
        3. Otherwise, the program text is found on STDIN.

        You might say, what about the shebang line? The shebang line is handled by the kernel - the interpreter found on the shebang line is started, and the content of the file (including the shebang line) is passed on STDIN. (This also explains why such interpreters always use # as the start of the comment).

        Abigail

perl -pne cat
by japhy (Canon) on Jun 03, 2002 at 20:19 UTC
    My node title says it all.

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: 'perl -p' ne 'cat'
by belg4mit (Prior) on Jun 03, 2002 at 20:11 UTC
    I think the real key lies in carefully reading what the manpage is telling you. It *wraps* your program with the supplied chunk of code. Without -e, or a file it drops down to STDIN (which of course is not going to be valid code in this case).

    A shebang with just -p would then be cat because the remainder of the file is valid perl (type perl on the command line, you're interactive mode. type C-d or F6 etc. (platform dependent) et voila. fini. no complaints)

    --
    perl -pew "s/\b;([mnst])/'$1/g"

(tye)Re: 'perl -p' ne 'cat'
by tye (Sage) on Jun 04, 2002 at 19:06 UTC

    At first, I was thinking I could support "perl -p" (not in the #! line) giving a helpful message since it is expecting both its script and its input from STDIN. But I immediately thought of using a "TTY" as STDIN such that you can have two "ends of file" on the one STDIN:

    shell> stty eof ^Z shell> perl -p >>notes BEGIN { print ''.localtime(),$/ } $_= "$.: $_" CTRL-Z Here are my notes for today. I should really make this a real script. CTRL-Z

    But then I realized you can use __END__ to do this trick anywhere:

    shell> cat script $_= "$.: $_"; __END__ Testing this. shell> perl -p <script 1: Testing 2: this.

    Granted, I haven't come up with a great use of this feature, but I'm reluctant to promote disabling it merely based on my lack of imagination. (:

            - tye (but my friends call me "Tye")

      I often add cases of test data after __END__ or __DATA__ in scripts that use while(<>) loops --- and I used to always switch between <> and <DATA> for testing purposes (and usually forgot to switch back when done). I recall being quite happy a few years back when I realized ("Doh!") I could just leave the bare diamond op and run the script on the test data via  perl -w < script.pl. Actually, I mostly test within the editor by sending the buffer to a filter of  perl -w with output directed to another buffer, but its the same thing.

Re: 'perl -p' ne 'cat'
by stefp (Vicar) on Jun 03, 2002 at 22:00 UTC
    My remark is not specific to the problem that grinder runs into. Many commands default to read the standard output when given no file parameters. If this is not the desired beheavior, on systems that support it, just append /dev/null, so if your list of file parameters happens to be empty, the command will not defaults to STDIN because the /dev/null device acts like an empty file.

    -- stefp -- check out TeXmacs wiki

Re: 'perl -p' ne 'cat'
by Aristotle (Chancellor) on Jun 03, 2002 at 23:16 UTC

    Actually, I've used -p on the shebang to good effect. It can make simple scripts a lot simpler.

    I've even written a CGI script where I had -pwTF/something/ on the shebang. :-)
    ____________

    Makeshifts last the longest.
Re: 'perl -p' ne 'cat'
by buckaduck (Chaplain) on Jun 04, 2002 at 14:26 UTC

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (3)
As of 2024-04-19 17:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found