How can I perform a substitutions on multiple variables whose names I don't know ahead of time?
-
06-07-2019 - |
Question
I'm working on a Perl script where the user adds a number of set variables at the beginning of the script, all prefixed with $XX
, as seen below. The user-set variables, however, need to go through a short transformation function to clean them up.
Is there a way to run the sub on all the variables with the $XX
prefix?
my $XXvar1 = "something";
my $XXvar2 = "something";
my $XXvar3 = "something";
my $XXvar4 = "something";
sub processVar {
my $fixVar = $_[0];
# Do stuff
return $fixVar;
}
# This obviously doesn't work. Use some kind of loop or something? How...
$XXvar* = processVar($XXvar*);
Edit: I'm trying to do this now with a hash, as per some suggestions on Google:
my %XX;
$XX{var1} = "something 1";
$XX{var2} = "something 2";
$XX{var3} = "something 3";
$XX{var4} = "something 4";
I can then work with the keys and values in for
or while
loops. However, how can I reassign each variable to the transformed one in the loop?
Edit again:
Got it. This for
loop processes all the variables successfully:
for my $key ( keys %XX ) {
$XX{$key} = processVar($XX{$key});
}
I'm definitely going to try to make a configuration file now, though, as suggested below. Now I just have to figure that out :)
Solution
Instead of users editing the source and providing odd variable names, use a configuration file instead. Every user can get his own configuration file. There are several modules on CPAN to handle configuration files of just about any format, and I talk about ways to configure Perl programs in a chapter of Mastering Perl. It's certainly a lot easier than the tricks you'd need to do to magically pick up these variable names.
OTHER TIPS
#!/usr/bin/perl
use strict;
use warnings;
my $XXvar1 = "something";
my $XXvar2 = "something";
my $XXvar3 = "something";
my $XXvar4 = "something";
my @values;
for ( 1 .. 4 ) {
push @values, eval '$XXvar' . $_;
}
processVar(@values);
sub processVar {
print "@_";
}
Just for the fun of it. But don't do this it's evil :-)
use PadWalker qw(peek_my peek_our peek_sub closed_over);
my $XXvar1 = "something1a";
my $XXvar2 = "something2b";
my $XXvar3 = "something3c";
my $XXvar4 = "something4d";
my $noXXvar = "something5e";
#remove last character
sub clean {
my $h = peek_my(1);
while(my ($key, $value) = each(%$h)) {
if ($key =~ /^\$XXvar.+/) {
chop ${$h->{$key}}
}
}
}
clean();
print "$XXvar1\n"; //something1
print "$XXvar2\n"; //something2
print "$XXvar3\n"; //something3
print "$XXvar4\n"; //something4
print "$noXXvar\n"; //something5e
My Perl is a bit rusty so there surly is a shorter/cleaner version of it.