如何在哈希中打印数组内容?我正在使用Dumper,因此您可以看到我正在解析的数据。
print Dumper \%loginusers;
for my $key ( keys %loginusers ) {
my $value = $loginusers{$key};
print "$key => $value\n";
}
printf "%s %-32s %-18s\n","User","Hostname","Since";
输出
$VAR1 = {
'server1.localdomain.com:8080' => [
', 'user=user1
' 'since=2017-03-10 13:53:27
]
};
server1.localdomain.com:8080 => ARRAY(0x1584748)
User Hostname Since
正如你所看到的那样,有一个ARRAY(0x1584748)并且我不知道如何从哈希中获取该值。
我希望看到的是:
User Hostname Since
user1 server1.localdomain.com:8080 2017-03-10 13:53:27
非常感谢能够提供帮助的人。
更新: 因此,在尝试此操作后,查看数据的外观:
foreach my $key (keys %loginusers)
{
print "For $key:\n";
print "\t|$_|\n" for @{$loginusers{$key}};
}
输出如下:
For server1.localdomain.com:8080:
| |user=user1
| |since=2017-03-10 13:53:27
更新: 尝试在代码中添加这些:
foreach my $key (keys %loginusers)
{
my @fields =
map { s/^\s*//; s/\s*\Z//; s/\s*\n\s*/ /g; $_ }
grep { /\S/ }
@{$loginusers{$key}};
print "For $key:\n";
print "$_\n" for @fields;
}
并使用两个示例代码:
printf "%-8s %-32s %s\n", qw(User Hostname Since);
foreach my $key (keys %loginusers)
{
my %field = map { /\s*(.*?)=\s*(.*)/ } @{$loginusers{$key}};
my ($host, $rgsender, $port) = split /:/, $key;
printf "%-8s %-32s %s\n", $field{user}, $host, $field{since};
}
my $newusers;
for my $host ( keys %loginusers ) {
local $/ = "\r\n"; #localised "input record separator" for the "chomp"
%{$newusers->{$host}} = map { chomp; split /=/,$_,2 } @{$loginusers{$host}};
}
undef %loginusers; #not needed anymore
#print "NEW STRUCTURE: ", Dumper $newusers;
printline( qw(User Hostname Since) );
printline($newusers->{$_}{user}, $_, $newusers->{$_}{since}) for (keys %$newusers);
sub printline { printf "%-8s %-32s %-18s\n", @_; }
以下是结果:
User Hostname Since
user1 server1.localdomain.com:8080 2017-03-10 13:53:27
User Hostname Since
user1 server1.localdomain.com:8080 2017-03-10 13:53:27
答案 0 :(得分:2)
哈希值是标量,可以参考。这就是我们构建复杂数据结构的方式。你的显然有阵列参数,所以你需要取消引用它们。像
这样的东西foreach my $key (keys %hash) {
say "$key => @{$hash{key}}";
}
请参阅教程perlretut和有关数据结构的食谱perldsc。
来自Dumper
的奇怪输出表明值(或更差)周围可能存在前导/尾随空格,需要将其清除。在澄清之前,我将假设像
'server1.localdomain.com:8080' => ['user=user1', 'since=2017-03-10 13:53:27']
为了获得所需的输出,您需要拆分每个元素
printf "%-8s %-32s %s\n", qw(User Hostname Since);
foreach my $key (keys %hash)
{
my ($user, $since) = map { /=\s*(.*)/ } @{$hash{$key}};
printf "%-8s %-32s %s\n", $user, $key, $since;
}
对于每个值,我们取消引用它并通过map传递。 map
块中的代码(应用于每个元素)将拉出=
之后的代码。给定数据,第一个是用户,第二个是时间戳。由于这是一个数组(而不是哈希),我假设订单是固定的。如果没有,请从=
的两边获取字符串并分析它们以查看哪一个去哪里。或者更好地使用哈希
my %field = map { /\s*(.*?)=\s*(.*)/ } @{$hash{$key}};
其中.*?
是.*
的非贪婪版本,直到第一个 =
为止。然后打印为
printf "%-8s %-32s %s\n", $field{user}, $key, $field{since};
并且您不依赖于arrayref中的订单。请参阅answer by jm666,了解从一开始构建此内容的良好且一致的方法。
使用上面显示的哈希打印
User Hostname Since user1 server1.localdomain.com:8080 2017-03-10 13:53:27
我根据显示的数据使用了8
和32
宽度。为了更精确,有表格输出模块。如果您手动执行此操作,则需要预先处理并在键和/或值中找到每列的最长单词,然后在printf
的第二遍中使用这些长度。
似乎Dumper
被奇怪的数据搞糊涂了。看看我们做了什么
foreach my $key (keys %loginusers)
{
print "For $key:\n";
print "\t|$_|\n" for @{$loginusers{$key}};
}
要清理您可以尝试的数据
foreach my $key (keys %loginusers)
{
my @fields =
map { s/^\s*//; s/\s*$//; s/\s*\R\s*/ /g; $_ }
grep { /\S/ }
@{$loginusers{$key}};
print "For $key:\n";
print "$_\n" for @fields;
}
grep
获取输入列表并过滤掉其块内的代码评估为false的元素。这里我们至少需要一个非空格字符。然后它的输出进入map
,删除所有前导和尾随空格,并用空格替换所有换行符。
答案 1 :(得分:2)
您的数据结构并不是很好。我会将它转换为更好的,使用:
#convert to better structure
my $newusers;
for my $host ( keys %loginusers ) {
%{$newusers->{$host}} = map { chomp; split /=/,$_,2 } @{$loginusers{$host}};
}
undef %loginusers; #the old not needed anymore
print "NEW STRUCTURE: ", Dumper $newusers;
转储现在看起来像:
NEW STRUCTURE: $VAR1 = {
'server1.localdomain.com:8080' => {
'user' => 'user1',
'since' => '2017-03-10 13:53:27'
}
};
以上印刷后很简单:
printline( qw(User Hostname Since) );
printline($newusers->{$_}{user}, $_, $newusers->{$_}{since}) for (keys %$newusers);
sub printline { printf "%-8s %-32s %-18s\n", @_; }
对于解释,请阅读@ zdim的优秀答案(并接受他的回答:))
完整代码
use 5.014;
use warnings;
use Data::Dumper;
my %loginusers = (
'server1.localdomain.com:8080' => [
"user=user1\r\n", # you probably have the \r too
"since=2017-03-10 13:53:27\r\n",
]
);
say "OLD STRUCTURE: ", Dumper \%loginusers;
#convert to better structure
my $newusers;
for my $host ( keys %loginusers ) {
%{$newusers->{$host}} = map { s/[\r\n]//g; split /=/, $_, 2 } @{$loginusers{$host}}; #removes all \r and \n
}
undef %loginusers; #not needed anymore
say "NEW STRUCTURE: ", Dumper $newusers;
printline( qw(User Hostname Since) );
printline($newusers->{$_}{user}, $_, $newusers->{$_}{since}) for (keys %$newusers);
sub printline { printf "%-8s %-32s %-18s\n", @_; }
结果:
OLD STRUCTURE: $VAR1 = {
'server1.localdomain.com:8080' => [
'user=user1
',
'since=2017-03-10 13:53:27
'
]
};
NEW STRUCTURE: $VAR1 = {
'server1.localdomain.com:8080' => {
'user' => 'user1',
'since' => '2017-03-10 13:53:27'
}
};
User Hostname Since
user1 server1.localdomain.com:8080 2017-03-10 13:53:27
您的数据中可能还有\r
。请参阅更新的代码。