Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

Re: shebang anomaly

by choroba (Bishop)
on Apr 18, 2018 at 21:16 UTC ( #1213141=note: print w/replies, xml ) Need Help??

in reply to shebang anomaly

Yes, shebang line is split into the interpreter and parameter, not parameters. See Silly things to do with shebang lines for some hints how to workaround the limitation.

($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

Replies are listed 'Best First'.
Re^2: shebang anomaly
by perlboy_emeritus (Sexton) on Apr 18, 2018 at 22:48 UTC
    Thanks choroba, but I don't think that article is on point for my problem. Let me state it again but more precisely. Every one of my Perl scripts has these two opening lines:
    #!/usr/bin/env perl -w ##!/usr/bin/env perl -wd

    I switch between these two lines, the first for ordinary runs, the second for debug runs. When I wish to debug I invert the lines, comment out the second, uncomment the first and proceed. Both these shebang lines fail in debian but work correctly in macOS. In debian I cannot have any argument to perl from an /usr/bin/env shebang despite rtfm. That page says the command can take an argument. True, if the argument was an argument list I would certainly quote it so that it appears as a single argument. In both of those example shebangs, I cannot have any arguments no matter how I quote them, and I've tried every quote option there is.

      The shebang line has never been specified as part of POSIX, SUS, LSB or any other specification. AFAIK, it hasn't even been properly documented.
      There is a rough consensus about what it does: take everything between the ! and the \n and exec it. The assumption is that everything between the ! and the \n is a full absolute path to the interpreter. There is no consensus about what happens if it contains whitespace.

      1 Some operating systems simply treat the entire thing as the path. After all, in most operating systems, whitespace or dashes are legal in a path.
      2 Some operating systems split at whitespace and treat the first part as the path to the interpreter and the rest as individual arguments.
      3 Some operating systems split at the first whitespace and treat the front part as the path to the interpeter and the rest as a single argument (which is what you are seeing).
      4 Some even don't support shebang lines at all.

      Thankfully, 1. and 4. seem to have died out, but 3. is pretty widespread, so you simply cannot rely on being able to pass more than one argument.

        Option 3 is much like MS DOS and its successors: make every program parse its own command line.

        Given that quoting in DOS is so difficult, most people don't try to write perl one-liners there. (Granted, it's hard enough in *shell sometimes.)

        Quantum Mechanics: The dreams stuff is made of

      I don't know if you ever gathered this from the other replies, but from choroba's "interpreter and parameter" and your "in both of those example shebangs, I cannot have any arguments" shows that, at least originally, you didn't understand. In the shebangs

      #!/usr/bin/env perl -w ##!/usr/bin/env perl -wd
      The "/usr/bin/env" is the interpreter, and "perl -w" or "perl -wd" is the single parameter (argument). Because it's one entity, then some versions of env will try to run "perl -w", and doesn't find anything to run that's P E R L SPACE DASH W as the name. (the same as you might get on other systems if you tried /usr/bin/env 'perl -w' or /usr/bin/env 'perl\ -w'.)

      Apart from all the examples given, there is a script in that page called "cmd" which allegedly will solve your problem by using: #!cmd /usr/bin/env perl -w. However, unless I am doing something wrong, it does not work for me. Although it should because what it does is straight-forward: breaks the command line and spawns yet another perl process with these args and your actual perl script.

      Maybe you will have better luck than me if you were to try having two shell scripts and calling perl differently?

        I contacted the maintainers of GNU coreutils of which env is a component and the answer I got really pissed me off, so I am forced to write my own env for use in debian (env behaves as expected in macOS). Printing the environment is the least difficult of what env does. That can be done with six lines of C, as in:

        #include <stdio.h> int main(int argc, char** argv, char** envp) { while (*envp++) { printf("%s\n", envp[-1]); } }

        The more challenging part, or parts, is the other things that env does and to make it work the same whether it is called from the command line or as a shebang. I subscribe to the principle of "least surprise", as in this article:

        I'll start with the code in cmd, as reported by choroba in an earlier post and go from there. It is fairly obvious to me that a well-behaved env could be implemented in any of C, bash or Perl. I might try them all, just to explore the possibilities. The GNU coreutils team should learn some humility, since a utility program's purpose is to enable users to do what they want to do, not assert some arrogant notion of "not-invented-here." I maintain that GNU env is either stupid or broken because it does not behave in a shebang the way it does when called from a command line. These two methods of invocation should not produce different results, no matter how aggressively someone asserts the program behaves correctly.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1213141]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (4)
As of 2019-11-21 05:55 GMT
Find Nodes?
    Voting Booth?
    Strict and warnings: which comes first?

    Results (103 votes). Check out past polls.