Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Prepocessing perl code / substing variables

by nataraj (Novice)
on Apr 15, 2019 at 18:32 UTC ( #1232596=perlquestion: print w/replies, xml ) Need Help??

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

Hi!

I have some script (i.e. backup script) that should work in different containers, do same job, but use different parameters in each container...

like

my $name = "my_second_project"; my $dir="/srv/msp"; do_backup($name,$dir); #this actually some pages of code

I want to put this script into git, so I do not know how to deal with paramethers that should be different in each container...

My idea was to change values to some substitution instructions and use some preprocessor that will do the substitution. Like

my $name = "%%NAME%%"; my $dir="%%DIR%%"; do_backup($name,$dir); #this actually some pages of code

and then create a small deploy script that has container specific configuration and just do preprocessing and installation. Like

do_preprocess("my_scripl.PL","/srv/msp/my_script.pl",{NAME=>"my_second_project",DIR=>"/srv/msp"});

So whenever I update my backup script and put it to git I can just git pull at the container, and run this installation script, and everything will continue working as before, but with new script version.

For variable substitution it is good to use some standard module. I guess I am not the first person who needs this. I carefully looked at the modules listed at https://metacpan.org/pod/distribution/Text-PerlPP/bin/perlpp in section ALTERNATIVES, but I did not like any of them. They are too old, or too new, part of some other project that have nothing in common with var substitution. These modules are not used in other modules and they are not part of debian (that is bad for me too)

Theoretically I can write Text::YetAnotherPP but there is a chance to get another unsupported module this way...

What is the right way to deal with my simple task? What would you advice?

Replies are listed 'Best First'.
Re: Prepocessing perl code / substing variables
by choroba (Bishop) on Apr 15, 2019 at 18:40 UTC
    If you just need simple values for a bunch of variables, use a config file. See Task::Kensho::Config for a list of recommended config modules, but there are many more on CPAN.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Prepocessing perl code / substing variables
by haukex (Chancellor) on Apr 15, 2019 at 19:01 UTC

    Don't try to parse Perl, only perl can parse Perl (modules like PPI come close, but still can't do everything). Use a Config:: module like choroba suggested, or if it's only one or two simple values, environment variables can sometimes be enough (see %ENV).

      It is not about parsing perl. It is about replacing %%VARIABLE_NAME%% with some value in the code while installing the script...
        It is not about parsing perl. It is about replacing %%VARIABLE_NAME%% with some value in the code while installing the script...

        If that's really all it's about, then why not just use perl -pie 's/%%VARIABLE_NAME%%/value/g' script.pl? Or s/%%(\w+)%%/$vars{$1}/g? (These are not rhetorical questions)

        A search and replace that doesn't parse Perl requires that the search pattern only appears in places where it should be replaced and nowhere else, i.e. it limits what Perl syntax can be used. If that's the case, then one can just as well use e.g. Template::Toolkit (or reinvent that wheel).

        As soon as one requires the preprocessing to have even the slightest awareness of Perl syntax, then we're talking about parsing Perl. If you don't believe me, give me an example and I'll give you the counterexample that breaks it ;-)

        In the situation you've described, config files or env vars are almost certainly the better solution than editing Perl source code.

Re: Prepocessing perl code / substing variables
by LanX (Archbishop) on Apr 16, 2019 at 00:59 UTC
    I can't see any reasonable use-case for regexing Perl° since it's incredible flexible already.

    Either

    • use a config file like already mentioned
    • require or do a dedicated file with constants only
    • pass values as arguments at startup and read them from @ARGV
    • set environment variables in %ENV
    or combine all of theses solutions.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

    °) only exception is probably $VERSION in modules

        Sure. And the world is a bad place. Did you ever avoid to load a module because it can execute arbitrary code?

        I would prefer command-line parameters but if the OP insists loading constants from a module isn't so bad IMHO:

        package MyConf { use constant NOSE => q(cuke); use feature qw(say); say __PACKAGE__; 1; }
        #!/usr/bin/env perl use strict; use warnings; use feature qw(say); use lib q(.); use MyConf; say qq(My nose isa @{[MyConf::NOSE]}!); __END__

        Best regards, Karl

        «The Crux of the Biscuit is the Apostrophe»

        perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

Re: Prepocessing perl code / substing variables (kraken released!)
by bliako (Priest) on Apr 16, 2019 at 10:54 UTC

    As others have said, what you are trying to do can be done by config files, a simple regex or templates. There is no need to re-invent the wheel or make it square.

    Another way is to control your deployment script with command line parameters: deploy.pl --script-name abc --location xyz/abc etc.

    And then there are ... autotools (written in Perl I think) which can do variable substitutions to source file templates. I would not use it just for a small task. I am mentioning it because you may want to use it as your main deployment/installation framework and be able to do ./configure && make all && make container && make backup && make push-git. It requires a lot of work to get started with it. Does your use-case justify it?

    Here is a skeleton just for the var-sub part (ripped from various sources on the net):

    # configure.ac AC_INIT([helloprog],[1.0],[abc@xyz.com]) AM_INIT_AUTOMAKE MYVAR="1234abc" AC_SUBST(MYVAR) AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([myscript.pl]) AC_OUTPUT
    # Makefile.am bin_SCRIPTS = myscript.pl

    Edit (forgot the perl script to have vars substituted):

    Edit2 (the name ends in .in denoting a template input, the .pl file will be produced from that. During the configure stage, not the make.):

    # myscript.pl.in # all @MYVAR@ will be substituted by value in configure.ac file my $var = "@MYVAR@"; print "var is : $var\n";

    bootstrap it using (just once):

    aclocal && automake --gnu --add-missing && autoconf

    and then:

    ./configure <params> && make all

    When IT people hear autotools, they will almost certainly parrot cmake, gradlew, maven as in a monty pythons sketch. Alas they are serious. Only a true hacker's heart fills with adrenaline when finally reached the state of ./configure && make all. But can you handle it?

    bw, bliako

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1232596]
Approved by marto
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (5)
As of 2019-06-27 02:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Is there a future for codeless software?



    Results (111 votes). Check out past polls.

    Notices?