OK, I've looked hard and have tried a myriad of variations to get this to work. I need some help from the perl experts.
First of all, I know, I know, don't use dynamic variable names! Well, I think I need to do so in this case. I'm fixing an inherited script. It has a set of variables that are formed with prefix
+ "_"
+ suffix
. This started small, but prefix is now a list of about 20 and suffix of about 50 -- a thousand different variables.
The script in some cases loops over these variables, using eval
to retrieve an individual value, etc.. This all works. The problem is, all uses of the different variables throughout the script, whether inside a loop on the prefix and/or suffix or just a hardcoded use, assume that these variables are globalized by using use var qw($varname)
. The number of use vars
hardcoded statements has grown out of control. Moreover, there are thousands of past input profile files that initialize these variables using global syntax, all of which need to continue to work.
I was hoping I could improve maintainability by doing the globalization step in a loop, dynamically creating the variable names one at a time, then globalizing them with use vars
or our
. Here is some code to show what I'm after. I've shown several options here, but each is actually a separate trial. I have tried other variations and cannot keep them straight anymore.
my @prefixes = ("one", "two", ..., "twenty");
my @suffixes = ("1", "2", ..., "50");
my $globalvars = "";
for my $suffix (@suffixes) {
for my $prefix (@prefixes) {
# option 1 -- remainder of #1 outside of loop
# NOTE: 1.a (no comma); 1.b (include comma between vars)
$globalvars .= "\$$prefix\_$suffix, ";
# option 2
eval "use vars qw(\$$prefix\_$suffix)";
# option 3
my $g = "$prefix\_$suffix";
eval ("use vars qw(\$$g)");
# option 4
eval ("our \$$g");
}
}
# option 1.a
use vars qw($globalvars);
# or option 1.b
my (eval "$globalvars");
:
:
:
# now use them as global variables
if ($one_1 eq ...) {
if ($one_10) {
It seems that the problem with "use vars" (besides the fact that it is discouraged) is that the string inside qw has to be the actual variable name, not a dynamic variable name. The 'eval' options don't work, I think, because the scope only exists within the eval itself.
Is there a way to do this in perl?
string inside qw has to be the actual variable name, not a dynamic variable name
That's how qw
works, it quotes words, it does no interpolation. You don't have to use qw
with use vars
, though.
#! /usr/bin/perl
use warnings;
use strict;
my @global_vars;
BEGIN { @global_vars = qw($x $y) }
use vars @global_vars;
# strict won't complain:
$x = 1;
$y = 2;
BEGIN is needed here, because use vars
runs in compile time, and we need @global_vars to be already populated.
There's no need for eval EXPR
since there's no need to use qw
. qw
is just one way to create a list of strings, and one that's not particularly useful to your needs.
my @prefixes; BEGIN { @prefixes = qw( one two ... twenty ); }
my @suffixes; BEGIN { @suffixes = 1..50; }
use vars map { my $p = $_; map { '$'.$p.'_'.$_ } @suffixes } @prefixes;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With