Re: Why am I getting Can't use string (<string value>) as an ARRAY ref wile "strict refs" in use
by NetWallah (Canon) on Feb 27, 2019 at 22:17 UTC
|
Your attempted statement:
$mtab1[$ii][$jj]=$user;
attempts to access a 2-Dimensional array.
In other words, it expects
$mtab1[$ii]
to be an array (technically, an array-reference) that can be further indexed.
However, the value assigned to that is NOT an array - it is a scalar, assigned in the previous statement:
$mtab1[$ii]=$tmpval; ##<<< This is a SCALAR
That is why perl complains at run-time.
As a computer, I find your faith in technology amusing.
| [reply] [d/l] [select] |
Re: Why am I getting Can't use string (<string value>) as an ARRAY ref wile "strict refs" in use
by BillKSmith (Monsignor) on Feb 27, 2019 at 21:11 UTC
|
I am not sure what you are trying to do. Strictly speaking, perl does not have such a thing as a "multidimensional array". It simulates it very well with an "array of arrays" (or more accurately, an array of array references). You are storing a string in the $ii element of the array @mtab. In the next statement, you use the syntax for "array of arrays". Perl expects that $ii element to contain a reference to one of several arrays (with $jj as the index into that array). The message is telling you that the main array contains the string you stored there rather than a reference. I cannot give you the correct syntax without knowing what you are trying to do. I suspect that a hash would be a better data structure.
| [reply] |
|
|
perl -E'my %x; $x{1,2,3} = 4; print $x{1,2,3}, "\n";'
They're kinda weirdly implemented and not really used much.
| [reply] [d/l] |
|
|
There's also multidimensional hashes [...] They're kinda weirdly implemented and not really used much.
Basically, all list elements are joined by $; (defaults to \034 = \x1C = ASCII FS) before using them as hash key. This is not multidimensional, it is just a poor emulation used mainly for awk compatibility.
Problems:
- The list elements must not contain the value of $; or else your data becomes garbage.
- Of course, you should not modify $; at runtime or else your data becomes garbage again.
- keys and each return the joined keys, not lists of key parts. There is no automatic split.
- The syntax does not work for slices.
Alexander
--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
| [reply] [d/l] [select] |
|
|
I found a description of this at Multi dimensional array emulation. It looks like it is creating a hash key from the list, "1,2,3". This seems like it could be a good way to implement a sparse array.
use warnings;
use strict;
use Data::Dumper;
my %x;
$x{1,2,3} = 4;
print $x{1,2,3}, "\n";
print Dumper(\%x);
__DATA__
4
$VAR1 = {
'123' => 4
};
| [reply] [d/l] |
Re: Why am I getting Can't use string (<string value>) as an ARRAY ref wile "strict refs" in use
by poj (Abbot) on Feb 27, 2019 at 21:25 UTC
|
It would be helpful if you could show a sample of the input file and the required output. Are you trying to load a file into an 2 dimension array like this perhaps ?
#!perl
use strict;
my $dir = 'C:/CCI/scci_clearcase/';
my $infile = $dir.'temp3_out.txt';
open IN,'<',$infile
or die "Could not open $infile : $!";
# Load Metrics table
#
my @table = ();
while (my $line = <IN>) {
chomp $line;
my ($dum1,$dum2) = split / /,$line,2;
my ($i,$j,$k,$l) = split /,/,$dum1,4;
my ($product,$date,$hour,$user) = split /,/,$dum2,4;
push @table,[$i,$j,$k,$l,$product,$date,$hour,$user];
}
close IN;
my $outfile = $dir.'temp2_out.txt';
open OUT,'>',$outfile
or die "Could not open $outfile : $!";
for my $rec (@table){
my ($i,$j,$k,$l,$product,$date,$hour,$user) = @$rec;
print OUT "$i, $j, $k, $l user='$user' mtab='$product $date $hour'
+ \n";
}
close OUT;
poj | [reply] [d/l] |
Re: Why am I getting Can't use string (<string value>) as an ARRAY ref wile "strict refs" in use
by bliako (Abbot) on Feb 28, 2019 at 11:28 UTC
|
Maybe you should consider using a hashtable to store the information you parse out from each line of your input, e.g.:
mtab[$ii] = {
'product' => $product,
'date' => $date,
'hour' => $hour,
...
};# I am a hash(ref) stored in an array
I am pretty sure that $mtab[$i][$j][$k][$l]=$user; is not doing what you have in mind - whatever that is. Be warned that Perl arrays are not sparse so if your $i,$j,$k,$l are some large-ish number then you have just created a 4-dimensional monster in RAM.
Perl arrays are not sparse. In other words, if you have a 10,000th element, you must have the 9,999 other elements, too. They may be undefined, but they still take up memory. For this reason, $array[time( )], or any other construct that uses a very large integer as an array index, is a really bad idea. Use a hash instead. (Perl Cookbook, 2nd Edition by Nathan Torkington, Tom Christiansen)
bw, bliako | [reply] [d/l] [select] |
|
|
I initially tried a hash and got the same type of error. I then rewrote the code to work with tables and it still did not work. I would rather use hashes. Can someone please show me why I am getting the error and hopefully the syntax to correct it. If I ignore the error then the hash table has the incorrect entries. The error I received was:
Can't use string ("Wed") as a HASH ref while "strict refs" in use at test3.pl line 51,
My input file was:
lmutil - Copyright (c) 1989-2009 Flexera Software, Inc. All Rights Res
+erved.
Flexible License Manager status on Wed 1/2/2019 07:00
[Detecting lmgrd processes...]
License server status: 27000@unodecx80
License file(s) on unodecx80: E:\Program Files (x86)\IBM\RationalR
+LKS\common\rational_server_perm.dat:E:\Program Files (x86)\IBM\Ration
+alRLKS\common\rational_server_temp.dat:
unodecx80: license server UP (MASTER) v11.10
Vendor daemon status (on unodecx80):
ibmratl: UP v11.10
Feature usage info:
Users of ClearCase: (Total of 10 licenses issued; Total of 1 license
+ in use)
"ClearCase" v1.00000, vendor: rational
floating license
amlove unodecx86 WI_zfTVVG-n7Ph2jhkOo #u#amlove#u# (v1.0) (unodecx
+80/27000 615), start Wed 1/2 6:56 (linger: 1800)
Users of ADALangPack: (Total of 1 license issued; Total of 0 license
+s in use)
The following was my code:
#!/usr/bin/perl
use strict;
use warnings;
my $mydebug1=1;
my $val="X";
my $k1="";
my $k2="";
my $k3="";
my $k4="";
my %metrics = ();
my $sysacc="";
my $origsys="";
my $product="";
my $day="";
my $date="";
my $hour="";
my $skip=1;
my $user="";
my $dum1="";
my $dum2="";
my $dum3="";
my $dum4="";
my $dum5="";
my $dum6="";
my $dum7="";
my $cnt=0;
my $found=0;
my $checkval="Users of";
my $str = "";
open (LICIN, "<C:\\SCCI\\scci_clearcase\\All_license_info_Jan2019_samp
+le\.txt");
while ($str = <LICIN>) {
chomp $str;
if ($str =~ /^Flexible License/) {
($dum1,$dum2,$dum3,$dum4,$dum5,$day,$date,$dum6) = split(/ /,$
+str,8);
($hour,$dum1) = split(/:/,$dum6,2);
next;
}
if ($str =~ /$checkval/) {
if ($str =~ /Users of ClearCase/) {
$str = <LICIN>;
$str = <LICIN>;
$str = <LICIN>;
$str = <LICIN>;
while ($str = <LICIN>) {
chomp $str;
last if ($str eq "");
$str =~ s/^\s+//;
($user,$sysacc,$origsys,$dum1) = split(/ /,$str,4);
$product="ClearCase";
$metrics{$product}{$date} = $day;
$metrics{$product}{$date}{$hour}{$user} = $val;
}
}
next;
}
}
#
# print hash table
#
if ($mydebug1) {
for $k1 (keys (%metrics)) {
print "k1 = $k1 \n";
for $k2 (keys(%{ $metrics{$k1} })) {
print "k2 = $k2 \n";
for $k3 (keys(%{ $metrics{$k1}{$k2} })) {
print "k3 = $k3 \n";
for $k4 (keys(%{ $metrics{$k1}{$k2}{$k3} })) {
print "k4 = $k4 \t k4val = $metrics{$k1}{$k2}{$k3}
+{$k4}\n";
}
}
}
}
}
| [reply] [d/l] |
|
|
$metrics{$product}{$date} = $day;
$metrics{$product}{$date}{$hour}{$user} = $val;
So, on line 50 you set $metrics{$product}{$date} to be a scalar and then on line 51 you try to treat it as a hash ref. That's incompatible. | [reply] [d/l] [select] |
|
|
Following #2 in Basic debugging checklist, I would recommend printing out the hash after every time you assign to a key or subkey of your %metrics hash. Because it's a complex structure, use Data::Dumper, as:
use Data::Dumper;
...
# after some assignment like
$metrics{$product}{$date} = $day;
print STDERR Dumper \%metrics;
$metrics{$product}{$date}{$hour}{$user} = $val;
print STDERR Dumper \%metrics;
as a one liner, with hardcoded values, for the first assignment and print:
C:\usr\local\share\PassThru\perl>perl -MData::Dumper -le "$metrics{pro
+duct}{today} = 'Wed'; print STDERR Dumper \%metrics"
$VAR1 = {
'product' => {
'today' => 'Wed'
}
};
You might then notice that at the first print, the value of the 'today' key is a string, 'Wed', and not another { nested => hash }. With a string as the value of {today}, you cannot take another subkey (like {today}{12}), because strings don't have subkeys. I think you need to rethink your data structure. Maybe show us in the Data::Dumper-like notation printed above, what you do want your data to look like when you're done, and we can help you organize your data into that format.
| [reply] [d/l] [select] |
|
|
$calendar{$date} = $day;
poj | [reply] [d/l] [select] |
|
|
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my %lic_info;
my $pending_product="";
my $pending_user_count=0;
my %actions=(
"Flexible License Manager" => sub{
@lic_info{qw|DAY DATE TIME|} = $_[0]=~/ on (\w+) (\S+) (\S+)$
+/;
},
"Users of " => sub{
my ($product,$issued, $usecount) = $_[0]=~/Users of (\w+): \(
+Total of (\d+) license\w? issued; Total of (\d+) lic/;
$lic_info{$product}{ISSUED}= $issued;
$pending_user_count = $lic_info{$product}{USED}= $usecount;
$pending_product = $product;
},
);
my $regex = "(" . join ("|", keys %actions) . ")";
while (<DATA>){
if ( m/$regex/ ){
$actions{$1}->($_); # Where the work happens
}elsif ($pending_product){
next if m/^\s+$/;
next if m/floating license/;
next if m/\s*\S?$pending_product/;
push @{$lic_info{$pending_product}{USERS}},
m/(\S+)/;
--$pending_user_count or $pending_product = "";
}
}
print Dumper \%lic_info;
__DATA__
lmutil - Copyright (c) 1989-2009 Flexera Software, Inc. All Rights Res
+erved.
Flexible License Manager status on Wed 1/2/2019 07:00
[Detecting lmgrd processes...]
License server status: 27000@unodecx80
License file(s) on unodecx80: E:\Program Files (x86)\IBM\RationalR
+LKS\common\rational_server_perm.dat:E:\Program Files (x86)\IBM\Ration
+alRLKS\common\rational_server_temp.dat:
unodecx80: license server UP (MASTER) v11.10
Vendor daemon status (on unodecx80):
ibmratl: UP v11.10
Feature usage info:
Users of ClearCase: (Total of 10 licenses issued; Total of 1 license
+ in use)
"ClearCase" v1.00000, vendor: rational
floating license
amlove unodecx86 WI_zfTVVG-n7Ph2jhkOo #u#amlove#u# (v1.0) (unodecx
+80/27000 615), start Wed 1/2 6:56 (linger: 1800)
Users of ADALangPack: (Total of 1 license issued; Total of 0 license
+s in use)
OUTPUT:
$VAR1 = {
'ClearCase' => {
'USED' => '1',
'USERS' => [
'amlove'
],
'ISSUED' => '10'
},
'ADALangPack' => {
'ISSUED' => '1',
'USED' => '0'
},
'DATE' => '1/2/2019',
'DAY' => 'Wed',
'TIME' => '07:00'
};
Update: FYI/FWIW - I was a ClearCase admin in a previous job, decades ago, and I sympathize. That was what taught me perl - so good luck !
As a computer, I find your faith in technology amusing.
| [reply] [d/l] [select] |
|
|
I am tempted to try some code but I think it will save us all some time if you present your data. Not as a file, but as how you see it being parsed from a file-line to a data structure. In pseudo/abstract-code. Then, along with you, we can see if a hash is a good idea. It seems to me that you thought about how you want your data structure to be but you have some difficulty in doing it in Perl. So talk abstract if you have too.
| [reply] |