Over Interpolation of Variables in a Substitution

Discussion in 'Perl Misc' started by Dietrich, Jul 22, 2004.

  1. Dietrich

    Dietrich Guest

    Challenge:
    I have variables in a configuration file that read ${profile} or
    ${altdatabase}, etc. They are also the pattern that I am using for a
    substitution, but the challenge is that they get interpolated more
    (resolved/dereferenced) than I would like. I have found a way around
    them, but that means removing the use strict pragma and -w option in
    the magic cookie ( top line of of a shell or perl script).

    I initially had substitution problems. The pattern on the left was
    never found, as it resolved what $string_match would be and that was
    not a found regexp. This is what I mean by the title, Over
    Interpolation of Variables in a Substitution.

    My method to get the script to work is to add an extra $ to the
    substitution code as follows, in order to prevent the over
    interpolation:

    29 s/$$string_match/$resolved_value/;

    When use the apply the -w option to the Perl interpreter, the script
    still works, but it gives an message to the xterminal as follows:
    chd07 dev3cst $ timex populate_invars.esp-new ESP_CST_invars
    Use of uninitialized value in regexp compilation at
    ../populate_invars.esp-new line 29, <INVARS_READ> line 15.
    Use of uninitialized value in regexp compilation at
    ../populate_invars.esp-new line 29, <INVARS_READ> line 18.

    real 0.23
    user 0.17
    sys 0.06

    Here shows exactly what I want to happen with the output ( the
    INVARS_NW file handle as shown in the code below).

    chd07 dev3cst $ diff $OLDPWD/ESP_CST_invars $OLDPWD/ESP_CST_invarsnw
    15c15
    < DB_MAIN_NAME = '${profile}'
    ---
    > DB_MAIN_NAME = 'Nixon'

    18c18
    < DB_ARCHIVE_NAME = '${altdatabase}'
    ---
    > DB_ARCHIVE_NAME = 'cbrde29'


    So when I utilize the use strict pragma, the output totally is not
    what I want.

    chd07 dev3cst $ timex populate_invars.esp-new ESP_CST_invars
    Can't use string ("${profile}") as a SCALAR ref while "strict refs" in
    use at ./populate_invars.esp-new line 30, <INVARS_READ> line 15.

    real 0.20
    user 0.16
    sys 0.04



    The Code:
    This is the entire script. This version does not have the -w option
    being used, nor the use strict pragma:

    1 #! /opt/perl/bin/perl
    2
    3 # Dietrich Martin
    4 # July 15, 2004
    5 #- A test script for esp_put changes.
    6
    7 use Env;
    8 use English;
    9
    10 # $invars_file will be passed from esp_put.
    11 my $invars_file=$ARGV[0];
    12 my $invars_filenw=$invars_file."nw";
    13
    14 open (INVARS_NW, ">${CBRCONFIGPATH}/ESP_NEW/$invars_filenw")
    || die "Can't open $invars_filenw: $OS_ERROR";
    15
    16 open (INVARS_READ, "${CBRCONFIGPATH}/ESP_NEW/$invars_file")
    || die "Can't open $invars_file: $OS_ERROR";
    17 while (<INVARS_READ>)
    18 {
    19 # When there is the ${'.*'} regexp, perform substitution
    to record the environmental value.
    20 if ($ARG =~ /\${(.*)}/)
    21 # Look for the ${} pattern as in ${profile}.
    22 {
    23 my $string_match = $MATCH;
    24
    25 my $resolved_value = `echo $string_match`;
    26
    27 chomp ($resolved_value);
    28
    29 s/$$string_match/$resolved_value/;
    30
    31 print INVARS_NW $ARG;
    32 }
    33 else
    34 # In case there is no ${'.*'} regexp, copy the record
    from input anyway (comments & blank lines).
    35 {
    36 print INVARS_NW $ARG;
    37 }
    38 }
    39
    40
    41 close (INVARS_READ) || die "Can't close $invars_file:
    $OS_ERROR";
    42 close (INVARS_NW) || die "Can't close $invars_filenw:
    $OS_ERROR";


    Goal:
    To be able to do this same variable substitution, while using the use
    strict pragma and -w option to the interpreter.

    Reference:
    comp.lang.perl
    File Handle Reading Blues: Rereading a File Handle for Input


    Thank you for your time.
     
    Dietrich, Jul 22, 2004
    #1
    1. Advertising

  2. (Dietrich) wrote in
    news::

    > Challenge:


    Solution: Go to

    http://search.cpan.org/modlist/Option_Parameter_Config_Processing

    and choose an applicable module.

    > I have variables in a configuration file that read ${profile} or
    > ${altdatabase}, etc.


    Instead of this long-winded explanation, show a snippet of the actual
    configuration file. Does it look like the following?

    ${altdatabase} = 'noneofyourbusiness';

    How on earth can anybody help you if you omit such basic information?

    > They are also the pattern that I am using for a substitution, but
    > the challenge is that they get interpolated more
    > (resolved/dereferenced) than I would like.


    Huh?

    > I have found a way around them, but that means removing the
    > use strict pragma and -w option in the magic cookie ( top line
    > of of a shell or perl script).


    99.9% of the time, avoid anything that requires you to remove

    use strict;
    use warnings;

    > I initially had substitution problems. The pattern on the left was
    > never found, as it resolved what $string_match would be and that was
    > not a found regexp.


    The pattern on the left of what? The carpet in your office?

    > My method to get the script to work is to add an extra $ to the
    > substitution code as follows, in order to prevent the over
    > interpolation:
    >
    > 29 s/$$string_match/$resolved_value/;


    You make it very hard to follow your post. The line above has absolutely
    no meaning in isolation.

    >
    > When use the apply the -w option to the Perl interpreter, the
    > script still works,


    Your criterion for 'works' must be different than mine.

    > real 0.23
    > user 0.17
    > sys 0.06


    How is this information pertinent to anything?

    > Here shows exactly what I want to happen with the output ( the
    > INVARS_NW file handle as shown in the code below).
    >
    > chd07 dev3cst $ diff $OLDPWD/ESP_CST_invars $OLDPWD/ESP_CST_invarsnw
    > 15c15
    > < DB_MAIN_NAME = '${profile}'
    > ---
    >> DB_MAIN_NAME = 'Nixon'

    > 18c18
    > < DB_ARCHIVE_NAME = '${altdatabase}'
    > ---
    >> DB_ARCHIVE_NAME = 'cbrde29'


    Hmmmm ... So your configuration file has the following format


    DB_MAIN_NAME = '${profile}'
    DB_ARCHIVE_NAME = '${altdatabase}'

    You want to replace ${profile} and ${altdatabase} with values from the
    environment.

    Is this really so hard to state up-front? Don't immediately get furious
    at me for asking this question. You cannot solve a problem you cannot
    state.

    #! perl

    use strict;
    use warnings;

    my %env = (
    profile => 'Nixon',
    altdatabase => 'cbrde29',
    );

    while(<DATA>) {
    next unless /^(\w+)\s*=\s*'\${(\w+)}'\s*$/;
    print "$1 = $env{$2}\n";
    }

    __DATA__
    DB_MAIN_NAME = '${profile}'
    DB_ARCHIVE_NAME = '${altdatabase}'

    Of course, if you want to get the values from the real environment, you
    would use the %ENV hash.

    >
    > So when I utilize the use strict pragma, the output totally is
    > not what I want.
    >
    > chd07 dev3cst $ timex populate_invars.esp-new ESP_CST_invars
    > Can't use string ("${profile}") as a SCALAR ref while "strict refs" in
    > use at ./populate_invars.esp-new line 30, <INVARS_READ> line 15.


    add

    use diagnostics;

    to your script to ask perl to explain this message to you since you do
    not seem to want to find out what it means.

    > real 0.20
    > user 0.16
    > sys 0.04


    Why is this information pertinent here?


    > The Code:
    > This is the entire script. This version does not have the -w
    > option being used, nor the use strict pragma:


    I'd rather you did not post it then.

    > 1 #! /opt/perl/bin/perl
    > 2
    > 3 # Dietrich Martin
    > 4 # July 15, 2004
    > 5 #- A test script for esp_put changes.


    You make it very hard for a reader to copy and paste your script and run
    it. Don't put these line numbers here if you want to help others help
    you.

    > 6
    > 7 use Env;
    > 8 use English;


    Why not just learn the mnemonics and use them?


    --
    A. Sinan Unur
    d
    (remove '.invalid' and reverse each component for email address)
     
    A. Sinan Unur, Jul 22, 2004
    #2
    1. Advertising

  3. Dietrich

    Ben Morrow Guest

    Quoth (Dietrich):
    > Challenge:
    > I have variables in a configuration file that read ${profile} or
    > ${altdatabase}, etc. They are also the pattern that I am using for a
    > substitution, but the challenge is that they get interpolated more
    > (resolved/dereferenced) than I would like. I have found a way around
    > them, but that means removing the use strict pragma and -w option in
    > the magic cookie ( top line of of a shell or perl script).
    >
    > I initially had substitution problems. The pattern on the left was
    > never found, as it resolved what $string_match would be and that was
    > not a found regexp. This is what I mean by the title, Over
    > Interpolation of Variables in a Substitution.
    >
    > My method to get the script to work is to add an extra $ to the
    > substitution code as follows, in order to prevent the over
    > interpolation:
    >
    > 29 s/$$string_match/$resolved_value/;


    AAARGH!!! 'You can't just make shit up and expect the computer to
    understand' [mjd].

    Read the docs. The correct way to write what you want is

    s/\Q$string_match/$resolved_value/;

    .. What you have there is a symref: read perldoc perlref to understand
    what they are, why you just used one and why you shouldn't. In this
    case, the most straightforward reason why you shouldn't is because it
    does something completely different from what you thought it did: if
    $string_match = 'foo' this will look for a variable $foo and substitute
    *that* into the rexex.

    Ben

    --
    The cosmos, at best, is like a rubbish heap scattered at random.
    - Heraclitus
     
    Ben Morrow, Jul 23, 2004
    #3
  4. Dietrich

    Joe Smith Guest

    Dietrich wrote:

    > Challenge:
    > I have variables in a configuration file that read ${profile} or
    > ${altdatabase}, etc. They are also the pattern that I am using for a
    > substitution, but the challenge is that they get interpolated more
    > (resolved/dereferenced) than I would like.


    In that case, you need to use a backslash before the dollarsign.

    s/\$altdatabase/$altdatabase/g;
    $/\${profile}/${profile}/g;

    -Joe
     
    Joe Smith, Jul 25, 2004
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ian
    Replies:
    4
    Views:
    2,315
    Ben Bacarisse
    Feb 2, 2006
  2. Lord0
    Replies:
    1
    Views:
    624
    Lord0
    May 16, 2005
  3. Elhanan
    Replies:
    0
    Views:
    366
    Elhanan
    May 23, 2006
  4. kw
    Replies:
    2
    Views:
    104
    Brian McCauley
    Nov 17, 2005
  5. Replies:
    4
    Views:
    216
    Rainer Weikusat
    May 2, 2013
Loading...

Share This Page