in reply to Why am I getting Can't use string (<string value>) as an ARRAY ref wile "strict refs" in use

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

  • Comment on Re: Why am I getting Can't use string (<string value>) as an ARRAY ref wile "strict refs" in use
  • Select or Download Code

Replies are listed 'Best First'.
Re^2: Why am I getting Can't use string (<string value>) as an ARRAY ref wile "strict refs" in use
by 5NOMAD7 (Initiate) on Feb 28, 2019 at 13:31 UTC

    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"; } } } } }

      Lines 50 and 51 are:

      $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.

      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.

      If you want to build the hash

      $metrics{$product}{$date}{$hour}{$user} = $val;

      Then $metrics{$product}{$date} has to be a hash reference. It can't be used the store the day. If you need to store the day use a separate hash

      $calendar{$date} = $day;
      poj
      Here is some working code.

      Pretty printing is left as an exercise:

      #!/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.

      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.