Over Interpolation of Variables in a Substitution

D

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/;

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.
 
A

A. Sinan Unur

(e-mail address removed) (Dietrich) wrote in
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}'

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?
 
B

Ben Morrow

Quoth (e-mail address removed) (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
 
J

Joe Smith

Dietrich said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,989
Messages
2,570,207
Members
46,783
Latest member
RickeyDort

Latest Threads

Top