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

How do I get the same output below without using "eval" ?
$ #/* Get module version number */
$ export module='JSON::PP'; perl -M$module -e 'print eval("\$".$ENV{module}."::VERSION")'
$ 4.04

Replies are listed 'Best First'.
Re: Indirect variable expansion
by Tux (Canon) on Nov 18, 2024 at 09:37 UTC
    $ cpan V $ perl -MV=JSON::PP

    Enjoy, Have FUN! H.Merijn
Re: Indirect variable expansion
by LanX (Saint) on Nov 18, 2024 at 03:27 UTC
    Since you're not using strict 'refs'
    ~ $ export module='JSON::PP'; perl -M$module -e 'print ${$ENV{module}. +"::VERSION"}' 4.07~ $ ~ $

    Next time please use code tags instead of pre .

    Edit

    Or just use the VERSION method

    ~ $ export module='JSON::PP'; perl -M$module -e 'print $ENV{module}->V +ERSION' 4.07~ $ ~ $

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    see Wikisyntax for the Monastery

      This removes code injection[1] while simplifying the interface[2]:

      perl -e'use if 1, $ARGV[0]; print $ARGV[0]->VERSION' JSON::PP

      1. Well, we're still allowing the user to load and execute a module, but it handles bad module names much better.
      2. The input is specified once, and it avoids some traps.
      UPDATE

      Don't use this code, the correct $M is only visible inside the subprocess, hence the use has to happen inside.


      FWIW: you don't need to export explicitly if you use this special bash syntax. Note the missing ;

      ~$ M="Data::Dumper" perl -M$M -E'say $ENV{M}->VERSION' 2.188

      Edit

      Furthermore, -M doesn't seem to throw an error for unknown modules.

      So adding warnings -w to your execution will help you catch typos

      ~$ M="Data::Dumb" perl -M$M -wE'say $ENV{M}->VERSION' Use of uninitialized value in say at -e line 1.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      see Wikisyntax for the Monastery

        Furthermore, -M doesn't seem to throw an error for unknown modules.
        Yes, it does:
        perl -MNotRight -e 0 Can't locate NotRight.pm in @INC (you may need to install the NotRight + module) (@INC contains: ...
Re: Indirect variable expansion
by hippo (Archbishop) on Nov 18, 2024 at 09:36 UTC

    Let the shell do the interpolation for you:

    $ export module='JSON::PP'; perl -M$module -e "print \$$module::VERSIO +N . qq/\n/" 4.06

    🦛

Re: Indirect variable expansion
by Fletch (Bishop) on Nov 18, 2024 at 06:57 UTC

    Just as another answer my personal pmver shell function. Exits with error if any of the named modules aren't available.

    pmver () { perl -le '$exit=0;for $f (@ARGV) { eval qq{require $f}; if( $@ + =~ /locate (\S+)\.pm/ ) { print qq{$f not installed}; $exit=1;next} +print qq{$f: },${"${f}::VERSION"}||q{undefined}}exit $exit' "$@" }

    Edit: Apt point below. Historically I've used this checking if/what CPAN stuff's installed so that was my expected failure mode WRT require. A more bullet proof version would probably report $@ in any failure (and/or use Try::Tiny).

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

      If the module cannot be loaded for some other reason, this gobbles up the error message - that's not cool!