Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

unexpected results using -s switch

by mojodaddy (Pilgrim)
on Aug 04, 2007 at 22:14 UTC ( [id://630668]=perlquestion: print w/replies, xml ) Need Help??

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

I was reading about the -s switch in the Camel book and noticed something that I can't figure out. The following script is taken directly from the book (p. 499, 3rd ed.):
#!/usr/bin/perl -s if ($foo eq 'bar'){ print "true\n" }
When invoked like so:
mojodaddy@muchomojo:~$ perl foo_eq_bar.pl -foo=bar
it should print "true", or at least my reading of the text suggests that it should, but it prints nothing. This script:
#!/usr/bin/perl -s if ($foo){ print "true\n" }
prints "true" with either a -foo or a -foo=bar switch. And finally this script:
#!/usr/bin/perl -s if ($foo eq 'bar'){ print "true\n" } if ($foo){ print "woo\n" } print "woo-hoo\n" if $foo eq 'bar'; print "woopty-doo\n" if $foo;
will only ever print "woo" and "woopty-doo" whether it is invoked with a -foo or -foo=bar switch. Can anyone explain what's going on? Have I gone through the looking glass? Or do I just need a new pair of glasses?

Replies are listed 'Best First'.
Re: unexpected results using -s switch
by Anonymous Monk on Aug 04, 2007 at 22:40 UTC
    You have the perl -s at the top of the script but then you run the script with perl on the command line. Pick one. Either set the script to have execute permissions and then run the script or run the script from the command line with the -s option.
    bruce:0:~/tmp $ cat p.pl
    #!/usr/bin/perl -s
    #
    if ($foo eq "bar") { print "true\n" }
    bruce:0:~/tmp $ ls -l p.pl
    -rwxr-xr-x   1 bruce  bruce  59 Aug  5 08:36 p.pl
    bruce:0:~/tmp $ ./p.pl -foo=bar
    true
    bruce:0:~/tmp $ perl p.pl -foo=bar
    bruce:0:~/tmp $ 
    bruce:0:~/tmp $ perl -s p.pl -foo=bar
    true
    
      It's pretty tough to stump the band around here, isn't it? : )

      Doing as you suggest does produce the sought-after output:

      mojodaddy@muchomojo:~$ perl -s foo_eq_bar.pl -foo=bar true woo woo-hoo woopty-doo
      Still, I can't help wondering why only the "if ($foo eq 'bar')" script was affected while the "if ($foo)" script did what I expected regardless of where I put the -s.
Re: unexpected results using -s switch
by naikonta (Curate) on Aug 05, 2007 at 02:53 UTC
    With -s switch, then any switch to the script will be treated as boolean switch unless supplied with argument. So -foo will set $foo to 1, and -foo=anything will set $foo to anything.
    $ cat foo.pl #!/usr/bin/perl -s use strict; use vars '$foo'; print $foo, "\n"; $ ./foo.pl -foo 1 $ ./foo.pl -foo=bar bar

    Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

      Interesting. So when NOT supplying an argument, it doesn't matter if I have the -s at the top of the script and call the script with perl on the command line. I only have to pick one when I do supply an argument.

      Is there a mnemonic for remembering that? : )

        Expanding AM's reply, when we use shebang (#!/usr/bin/perl), we have an advantage to make our program "a real program" by turning our source file's execute bit on. In this case, the OS will call the correspondent interpreter program (perl in this case) to process the file in question, and all perl switches (-w, -s, -T, etc) are taken into account. So we're able to say,
        $ ./program.pl # or if it's in known PATH: $ program.pl
        Of course, this only applies if the underlying OS supports it, such as Linux.

        OTOH, we are of course able to call the perl interpreter directly and feed it with the source file. This way, we can provide some extra switches not exist in the shebang, or even overriding switches in the shebang. It also means that executing a source file this way doesn't require the shebang to be declared in the source file. However, the perl interpreter will consider it if it does exist.

        Having said that, I think you can assure yourself about that "pick one", regardless of using -s (with our without argument to your own swithces) or not. Now let me suggest you that, if you're really serious about providing command line arguments for your program, use the more elegant modules from CPAN for parsing the arguments for you. One of them is Getopt::Long that comes with the standard Perl distribution.

        $ cat foo.pl #!/usr/bin/perl use strict; use warnings; use Getopt::Long; my %opts; GetOptions(\%opts, 'foo=s', 'v'); # '=s' modifier means foo needs argument, and it can be # any string (another modifier is '=i' for integer.) print "foo = $opts{foo}, verbose = $opts{v}\n"; $ perl foo.pl --foo=bar -v foo = bar, v = 1 $ ./foo.pl --for=bar -v foo = bar, v = 1
        Now, I'd say "pick any" instead of "pick one" :-) You don't have to use a hash to store the arguments, you can use direct scalar.
        $ cat foo.pl #!/usr/bin/perl use strict; use warnings; use Getopt::Long; use vars qw($foo, $verbose); GetOptions('foo=s' => \$foo, 'v' => \$verbose); # '=s' modifier means foo needs argument, and it can be # any string (another modifier is '=i' for integer.) print "foo = $foo, verbose = $verbose\n"; $ perl foo.pl --foo=bar -v foo = bar, v = 1 $ ./foo.pl --for=bar -v foo = bar, v = 1
        See Getopt::Long for detail.

        Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

      if i understood correctly, the matter is different:
      $ cat t.pl #!/usr/bin/perl print "foo=$foo\n"; $ perl t.pl -foo=bar foo=
      and that's is expected.
      $ cat t.pl #!/usr/bin/perl -s print "foo=$foo\n"; $ perl -s t.pl -foo=bar foo=bar
      and that's too, but:
      $ cat t.pl #!/usr/bin/perl -s print "foo=$foo\n"; $ perl t.pl -foo=bar foo=1
      if i call it without -s, but the shebang say -s, perl assign 1 which is neither bar or undef

      Oha

      update: with the help of dada i think we have figured out it was a bug in perl.c function init_argv_symbols. checking on dev.perl.org on latest 5.x sources seems fixed btw. could anyone confirm? it's long since i read C code...

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (6)
As of 2024-04-19 12:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found