Aldebaran has asked for the wisdom of the Perl Monks concerning the following question:
Hello monks,
I frequently replicate others' posts so as to help if I can, learn more of a gigantic language, and have new scripts that will improve my own capabilities. So it is that chungley2000 rolled in with a question that morphed into about how to get values from Config. I've been playing with the values for a couple days now, and I wrote a script to see what output resulted from the 4 method function calls that this module exports. I've commented out failed attempts to herd these values into lexical variables.
#!/usr/bin/perl -w
use 5.011;
use Config qw(myconfig config_sh config_vars config_re);
use Data::Dumper;
say myconfig();
say "---------------";
say config_sh();
say "---------------";
say config_vars();
say "---------------";
my $ref_Env = \%ENV;
say Dumper $ref_Env;
my $version = config_re("version");
say "version is $version";
# my $archname = $Config{'archname'}; #produces error: %Config unknown
say "---------------";
#my $ref_Config = \%CONFIG;
#say Dumper $ref_Config;
Abridged output, where I've commented on values with a double hashmark:
Summary of my perl5 (revision 5 version 26 subversion 1) configuratio
+n:
Platform:
osname=linux
osvers=4.9.0
archname=x86_64-linux-gnu-thread-multi
---------------
Author=''
CONFIG='true'
## big snip from say myconfig();
zcat=''
zip='zip'
---------------
##nothing for say config_sh();
---------------
$VAR1 = {
'TEXTDOMAIN' => 'im-config',
'SSH_AUTH_SOCK' => '/run/user/1000/keyring/ssh',
'IM_CONFIG_PHASE' => '2',
'PERL5LIB' => '/home/bob/perl5/lib/perl5',
## snip in ENV data
'LESSCLOSE' => '/usr/bin/lesspipe %s %s'
};
version is 1 ##config_re("version");
---------------
My experience with the large family of Config modules has been with Config::Tiny, where I have imported such values from an .ini file. Now I would like to import the values from the myconfig() method into a hash.
If I had to get values quick and dirty, I would create a temp file with Path::Tiny, then read it with Config::Tiny. But when you have the darn thing in memory already, it seems like a significant work-around, in particular, when you are only going to delete the file for being a security risk. I don't want these data to be persistent beyond the first few lines of a perl script. Other modules from the Config namespace seem promising, but, for example CONFIG::Hash seems like it might be the thing I'm looking for, but not quite. There are at least 12 screens of matches for Config in cpan.
I could also use bash to pipe these values, but do I really need a shell? It seems like there could be a perl-only solution to this, which is more portable. My question then is how to to herd the = joined and newline separated values from
config_vars()
into a hash.
Thank you for your comment,
Re: how to get Config values into a hash
by haukex (Archbishop) on Oct 15, 2018 at 21:15 UTC
|
Note that Config is not a module that reads configuration files, nor is it the base of the Config:: namespace, the latter being the CPAN modules that typically do read configuration files, like Config::Tiny.
Config is "all the information that was available to the Configure program at Perl build time ... Shell variables from the config.sh file (written by Configure) are stored in the readonly-variable %Config, indexed by their names." So in other words, it's the perl build configuration, which is fixed for each build of Perl at compile time.
The four functions (not methods) that you mention, myconfig, config_sh, config_vars, and config_re, are basically just alternate ways to get information out of Config. In the example code you showed, my $archname = $Config{'archname'}; does not work because you're only requesting those four functions to be exported from Config, but not the %Config hash. So you don't need to "import the values from the myconfig() method into a hash", that's %Config.
You can either just use the module in the basic fashion, where %Config is exported by default:
use Config;
my $archname = $Config{'archname'};
print "<$archname>\n";
Or, if you do want to export functions from the module, you need to request the export of %Config explicitly:
use Config qw/%Config config_vars/;
my $archname = $Config{'archname'};
print "<$archname>\n";
config_vars("archname","version");
| [reply] [d/l] [select] |
|
Thx, Haukex, you've been instrumental in helping me to disambiguate Config situations in such nodes as Re^5: redacting from config hash and node Re^3: redacting from config hash. I hope this isn't a three strikes, you're out scenario, as I fanned on this one pretty hard. I was unaware that this Config was stamped when the user's perl install was made. It's been revealing for me to poke around in this space as a guy who knows some C. I wanted to see if I could read Config.pm, so typed
locate Config.pm >1.txt
I might have had 20 candidates with many interesting features on their own right, but I think I narrowed it down to 3 that look like the Config.pm that gets used.
diff /usr/lib/x86_64-linux-gnu/perl/5.26.1/Config.pm /usr/lib/x86_64-l
+inux-gnu/perl-base/Config.pm >2.txt
diff /usr/lib/x86_64-linux-gnu/perl/5.26.1/Config.pm /usr/lib/x86_64-l
+inux-gnu/perl/cross-config-5.26.1/Config.pm >3.txt
diff /usr/lib/x86_64-linux-gnu/perl-base/Config.pm /usr/lib/x86_64-lin
+ux-gnu/perl/cross-config-5.26.1/Config.pm >5.txt
They weren't different from each other except for path. So I try to add functionality to a script to organize and probe these values. My next attempt fell apart when I tried to use Data::Dumper. What's more when I tried to work up the example from Data::Dumper, I couldn't get anywhere. I was able to cobble together a path for one of the Config.pm's using Path::Tiny and slurp it in. It's not horrendously long like some of this output, but to save the monastery's collective scrollfingers, I'll list the script and put abridged output between readmore tags:
$ cat 4.tk.pl
#!/usr/bin/perl -w
use 5.011;
use utf8;
use Config qw/%Config config_vars/;
use lib "1.псы/template_stuff";
use utils1 qw/print_hash/;
my $archname = $Config{'archname'};
print "<$archname>\n";
say "---------------";
config_vars( "archname", "version", "libpath", "perl", "scriptdir", "s
+itearchexp" );
say "---------------";
my $ref_Config = \%Config;
print Dumper $ref_Config; # print() on unopened filehandle Dumper
# print Dumper $Config; # Variable "$Config" is not imported
print_hash($ref_Config);
say "---------------";
use Path::Tiny;
my ($archlibexp, $version) = ($Config{archlibexp},$Config{version});
my $arch_path = path($archlibexp)->parent;
say "arch_path is $arch_path";
my $path_to_Config = path($arch_path,$version, "Config.pm");
my @lines = $path_to_Config->lines;
say "lines are @lines";
say "---------------";
my $ref2_Config = \%Config::Config;
print Dumper $ref2_Config;
say "---------------";
use ExtUtils::MakeMaker::Config;
say $Config{installbin};
say "---------------";
$Data::Dumper::Sortkeys = \&my_filter;
my $foo = { map { (ord, "$_$_$_") } 'I'..'Q' };
say "foo is %$foo";
# print Dumper $foo; # print() on unopened filehandle Dumper
print_hash($foo);
my $bar = { %$foo };
my $baz = { reverse %$foo };
print Dumper [ $foo, $bar, $baz ];
sub my_filter {
my ($hash) = @_;
# return an array ref containing the hash keys to dump
# in the order that you want them to be dumped
return [
# Sort the keys of %$foo in reverse numeric order
$hash eq $foo ? (sort {$b <=> $a} keys %$hash) :
# Only dump the odd number keys of %$bar
$hash eq $bar ? (grep {$_ % 2} keys %$hash) :
# Sort keys in default order for all other hashes
(sort keys %$hash)
];
}
$
How did I lose my grip on Data::Dumper so as not to be able to even work up the example code?
With 1000's of values in this hash, would I find a variable that contained the path that I think is probable for being the one actually used when during use Config ();? Not really. Output then source:
#!/usr/bin/perl -w
use 5.011;
use utf8;
use Config qw/%Config config_vars/;
use lib "1.псы/template_stuff";
use utils1 qw/print_hash/;
use Path::Tiny;
my ( $archlibexp, $version ) = ( $Config{archlibexp}, $Config{version}
+ );
my $arch_path = path($archlibexp)->parent;
say "arch_path is $arch_path";
my $path_to_Config = path( $arch_path, $version, "Config.pm" );
my @lines = $path_to_Config->lines;
# say "lines are @lines"; this works
say "---------------";
for ( keys %Config ) {
next if ($Config{$_} eq undef);
if ( $Config{$_} =~ m%/usr/lib/x86_64-linux-gnu/perl% ) {
say "$_ matched: $Config{$_}";
}
}
My question here is how does perl decide which Config.pm it uses?
Thank you for your comments, haukex; I've been following your webperl development and have gotten good initial results that I'm building on. | [reply] [d/l] [select] |
|
print Dumper $ref_Config; # print() on unopened filehandle Dumper
Looks like you're missing use Data::Dumper; at the top of the script. The error message is a little confusing because Perl is trying to interpret that print as Indirect Object Syntax (print FILEHANDLE LIST).
Other than that, looks like you've figured out @INC, and I already pointed out %INC, which will give you the location of the file that was actually loaded.
| [reply] [d/l] [select] |
|
|
$ ./2.cf.pl
</usr/lib/x86_64-linux-gnu/perl/5.26>
---------------
/home/bob/perl5/lib/perl5/x86_64-linux-gnu-thread-multi /home/bob/perl
+5/lib/perl5 /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.26.1 /us
+r/local/share/perl/5.26.1 /usr/lib/x86_64-linux-gnu/perl5/5.26 /usr/s
+hare/perl5 /usr/lib/x86_64-linux-gnu/perl/5.26 /usr/share/perl/5.26 /
+usr/local/lib/site_perl /usr/lib/x86_64-linux-gnu/perl-base
path is /usr/lib/x86_64-linux-gnu/perl/5.26/Config.pm
stat is File::stat=ARRAY(0x55f122748b70)
$VAR1 = bless( [
2054,
6591373,
33188,
1,
0,
0,
0,
3372,
1539824438,
1531923663,
1532749911,
4096,
8
], 'File::stat' );
path is /usr/lib/x86_64-linux-gnu/perl-base/Config.pm
stat is File::stat=ARRAY(0x55f122ad48c0)
$VAR1 = bless( [
2054,
6591655,
33188,
1,
0,
0,
0,
3373,
1539712704,
1531923663,
1532749916,
4096,
8
], 'File::stat' );
$ cat 2.cf.pl
#!/usr/bin/perl -w
use 5.011;
use utf8;
use Config qw/%Config config_vars/;
use Path::Tiny;
use Data::Dumper;
my $insarchname = $Config{'installarchlib'};
print "<$insarchname>\n";
say "---------------";
say "@INC";
foreach (@INC) {
my $path1 = path( $_, "Config.pm" );
if ( -f $path1 ) {
my $stat = $path1->stat;
say "path is $path1";
say "stat is $stat";
say Dumper $stat;
}
}
$
| [reply] [d/l] |
|
|
|