[英]Perl: Add hash as sub hash to simple hash
I looked at the other two questions that seem to be about this, but they are a little obtuse and I can't relate them to what I want to do, which I think is simpler.我看了另外两个好像是关于这个的问题,但是有点生硬,我不能把它们和我想做的事情联系起来,我认为这更简单。 I also think this will be a much clearer statement of a very common problem/task so I'm posting this for the benefit of others like me.我也认为这将是一个非常常见的问题/任务的更清晰的陈述,所以我发布这个是为了像我这样的其他人的利益。
I have 3 files, each file a list of key=value
pairs:我有 3 个文件,每个文件都有一个key=value
对列表:
settings1.ini设置1.ini
key1=val1
key2=val2
key3=val3
settings2.ini设置2.ini
key1=val4
key2=val5
key3=val6
settings3.ini设置3.ini
key1=val7
key2=val8
key3=val9
No surprise, I want to read those key=value
pairs into a hash to operate on them, so...毫不奇怪,我想将那些key=value
对读入 hash 以对它们进行操作,所以......
I have a hash of the filenames:我有一个 hash 的文件名:
my %files = { file1 => 'settings1.ini'
, file2 => 'settings2.ini'
, file3 => 'settings3.ini'
};
I can iterate through the filenames like so:我可以像这样遍历文件名:
foreach my $fkey (keys %files) {
say $files{$fkey};
}
Ok.行。
Now I want to add the list of key=value
pairs from each file to the hash as a sub-hash under each respective 'top-level' filename key, such that I can iterate through them like so:现在我想将每个文件中的key=value
对列表添加到 hash 作为每个相应“顶级”文件名键下的子哈希,这样我就可以像这样遍历它们:
foreach my $fkey (keys %files) {
say "File: $files{$fkey}";
foreach my $vkey (keys $files{$fkey}) {
say " $vkey: $files{$fkey}{$vkey}";
}
}
In other words, I want to add a second level to the hash such that it goes from just being (in psuedo terms) a single layer list of values:换句话说,我想向 hash 添加第二个级别,这样它就不再只是(用伪术语)单层值列表:
file1 => settings1.ini
file2 => settings2.ini
file3 => settings3.ini
to being a multi-layered list of values:成为一个多层值列表:
file1 => key1 => 'val1'
file1 => key2 => 'val2'
file1 => key3 => 'val3'
file2 => key1 => 'val4'
file2 => key2 => 'val5'
file2 => key3 => 'val6'
file3 => key1 => 'val7'
file3 => key2 => 'val8'
file3 => key3 => 'val9'
Where:在哪里:
my $fkey = 'file2';
my $vkey = 'key3';
say $files{$fkey}{$vkey};
would print the value将打印值
'val6'
As a side note, I am trying to use File::Slurp
to read in the key=value
pairs.作为旁注,我正在尝试使用File::Slurp
读取key=value
对。 Doing this on a single level hash is fine:在单个级别 hash 上执行此操作很好:
my %new_hash = read_file($files{$fkey}) =~ m/^(\w+)=([^\r\n\*,]*)$/img;
but - to rephrase this whole problem - what I really want to do is 'graft' the new hash of key=value
pairs onto the existing hash of filenames 'under' the top $file
key as a 'child/branch' sub-hash.但是-重新表述整个问题-我真正想做的是将新的 hash key=value
对“嫁接”到现有的 hash 文件名“位于”顶部$file
键下作为“子/分支”子哈希.
I use strict;
我use strict;
and so I have seen the所以我看到了
Can't use string ("string") as a HASH ref while "strict refs" in use at script.pl line <lineno>.
which I don't fully understand...我不完全明白...
Thank you Timur Shtatland , Polar Bear and Dave Cross for your great answers.感谢Timur Shtatland 、 Polar Bear和Dave Cross的出色回答。 In mentally parsing your suggestions it occurred to me that I had slightly mislead you by being a little inconsistent in my original question.在精神上分析你的建议时,我想到我在最初的问题中有点不一致而误导了你。 I apologize.我道歉。 I also think I see now why I saw the 'strict refs' error.我也想我现在明白为什么我看到“严格参考”错误了。 I have made some changes.我做了一些改变。
Note that my first mention of the initial hash of filename is correct .请注意,我第一次提到文件名的初始 hash是正确的。 The subsequent foreach examples looping through %files
, however, were incorrect because I went from using file1
as the first file key to using settings1.ini
as the first file key.然而,随后循环遍历%files
的 foreach 示例是不正确的,因为我从使用file1
作为第一个文件键改为使用settings1.ini
作为第一个文件键。 I think this is why Perl threw the strict refs
error - because I tried to change the key from the initial string to a hash_ref pointing to the sub-hash (or vice versa).我认为这就是 Perl 抛出strict refs
错误的原因——因为我试图将密钥从初始字符串更改为指向子哈希的 hash_ref(反之亦然)。
Have I understood that correctly?我理解正确吗?
There are several CPAN modules purposed for ini files.有几个用于 ini 文件的 CPAN 模块。 You should study what is available and choose what your heart desire.你应该研究可用的东西并选择你内心想要的东西。
Otherwise you can write your own code something in the spirit of following snippet否则,您可以本着以下代码片段的精神编写自己的代码
use strict;
use warnings;
use feature 'say';
use Data::Dumper;
my @files = qw(settings1.ini settings2.ini settings3.ini);
my %hash;
for my $file (@files) {
$hash{$file} = read_settings($file);
}
say Dumper(\%hash);
sub read_settings {
my $fname = shift;
my %hash;
open my $fh, '<', $fname
or die "Couldn't open $fname";
while( <$fh> ) {
chomp;
my($k,$v) = split '=';
$hash{$k} = $v
}
close $fh;
return \%hash;
}
Output Output
$VAR1 = {
'settings1.ini' => {
'key2' => 'val2',
'key1' => 'val1',
'key3' => 'val3'
},
'settings2.ini' => {
'key2' => 'val5',
'key1' => 'val4',
'key3' => 'val6'
},
'settings3.ini' => {
'key1' => 'val7',
'key2' => 'val8',
'key3' => 'val9'
}
};
To build the hash one layer at a time, use anonymous hashes.要一次构建 hash 一层,请使用匿名哈希。 Each value of %files
here is a reference to a hash, for example, for $files{'settings1.ini'}
:此处%files
的每个值都是对 hash 的引用,例如$files{'settings1.ini'}
:
# read the data into %new_hash, then:
$files{'settings1.ini'} = { %new_hash }
You do not need to predefine the hash as multi-layered (as hash of hashes) upfront.您不需要预先将 hash 预定义为多层(作为哈希的 hash)。
Also, avoid reinventing the wheel.另外,避免重新发明轮子。 Use Perl modules for common tasks, in this case consider something like Config::IniFiles for parsing *.ini
files将 Perl 模块用于常见任务,在这种情况下,考虑像Config::IniFiles这样的东西来解析*.ini
文件
SEE ALSO:也可以看看:
Anonymous hashes: perlreftut匿名哈希: perlreftut
Hashes of hashes: perldsc哈希的哈希值: perldsc
Perl makes stuff like this ridiculously easy. Perl 让这样的事情变得异常简单。
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
use Data::Dumper;
my %files;
# <> reads from the files given on the command line
# one line at a time.
while (<>) {
chomp;
my ($key, $val) = split /=/;
# $ARGV contains the name of the file that
# is currently being read.
$files{$ARGV}{$key} = $val;
}
say Dumper \%files;
Running this as:将其运行为:
$ perl readconf settings1.ini settings2.ini settings3.ini
Gives the following output:给出以下 output:
$VAR1 = {
'settings3.ini' => {
'key2' => 'val8',
'key1' => 'val7',
'key3' => 'val9'
},
'settings2.ini' => {
'key3' => 'val6',
'key1' => 'val4',
'key2' => 'val5'
},
'settings1.ini' => {
'key3' => 'val3',
'key1' => 'val1',
'key2' => 'val2'
}
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.