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

This is perl, v5.8.5 built for i386-linux-thread-multi This is perl, v5.6.1 built for i386-linux
I created a script
#! /usr/bin/perl -p __DATA__ hello goodbye
I expected this to print
hello goodbye
Instead it hangs waiting for standard input. Why?

Replies are listed 'Best First'.
Re: -p option with __DATA__
by jwkrahn (Abbot) on Nov 19, 2009 at 15:57 UTC
    #! /usr/bin/perl -p __DATA__ hello goodbye

    Is the same as:

    #! /usr/bin/perl while ( <> ) { } continue { print } __DATA__ hello goodbye

    You are not doing anything with the DATA filehandle.

        I guess what confuses me is that
        perl -MO=Deparse script.pl
        and
        perl -MO=Deparse < script.pl
        give (almost) the same output, but
        perl script.pl
        hangs as described, whereas
        perl < script.pl
        prints what I expected.

      ...which uses the 'diamond operator'. Normally, the diamond operator takes all the file names specified on the command line as arguments, combines the corresponding files into one big file, and then assigns a line from the big file to $_ each time through the loop. However, if you do not specify any file names as arguments on the command line, then the diamond operator reads from STDIN. Presumably, that is what you did, so your program is waiting for you to type in a line of text for the diamond operator to process (you would hit ctrl+D to signal end-of-file after typing in all your lines).

      Also, when you specify filenames as arguments on the command line, if you specify a file name as: -, then the diamond operator will read from STDIN for that portion of the big file.

        Normally, the diamond operator takes all the file names specified on the command line as arguments,

        Only when ARGV is provided as the handle or not handle is provided (since the diamond operator uses ARGV by default). That's because the diamond operator does none of that. It's all ARGV's doing.

        combines the corresponding files into one big file

        Yes, without actually combining the files on disk or in mem. In fact, using eof (with no argument or parens), you can detect when it's going to move to another file.

        and then assigns a line from the big file to $_ each time through the loop

        No, the diamond operator neither creates a loop nor assigns to $_. while provides the looping.

        However, if you do not specify any file names as arguments on the command line, then the diamond operator reads from STDIN.

        Again, only if ARGV is used as the handle since it's all ARGV's doing.

        if you specify a file name as: -, then the diamond operator will read from STDIN for that portion of the big file.

        ARGV uses the two arg version of open. It also allows arguments such as 'zcat compressed.gz |'. In other words, without using a shell, you can achieve the same using bash's <( zcat compressed.gz )

Re: -p option with __DATA__
by ikegami (Patriarch) on Nov 19, 2009 at 16:03 UTC

    -p is documented to do while (<>), not while (<DATA>)

    The default file handle, ARGV, reads from the files named in @ARGV (i.e. supplied on the command line) or STDIN if no files were supplied.

Re: -p option with __DATA__
by jethro (Monsignor) on Nov 19, 2009 at 16:04 UTC

    The stuff in __DATA__ is read with the filehandle DATA, not with the magical default-filehandle of while (<>) {

Re: -p option with __DATA__
by codeacrobat (Chaplain) on Nov 19, 2009 at 19:44 UTC
    try aliasing DATA to ARGV.
    #!/usr/bin/perl -p BEGIN{*ARGV=*DATA} __DATA__ hello world

    print+qq(\L@{[ref\&@]}@{['@'x7^'!#2/"!4']});