http://www.perlmonks.org?node_id=1026308


in reply to Generic Data Collection

Please let me know what further details I can share to give you better insight on answering my question.
Post a small snippet of the output of the command (as few lines as possible). You can also use Super Search to see if anyone has done anything similar.

Replies are listed 'Best First'.
Re:^2 Generic Data Collection
by Deep_Plaid (Acolyte) on Mar 31, 2013 at 13:00 UTC

    Here's a snippet of the code I am working with:

    $flexlm_cmd = "lmutil lmstat -f ${product}"; #other junk $license_cmd = "$flexlm_cmd"; open LICENSES, "$license_cmd |" || die "Can't execute ($license_cmd +) \n$!\n"; while (<LICENSES>) { $data_line = $_; # my @data = split; #print if grep $_ > 99, @data[1..$#data]; if ($data_line =~ /27000 (\d+)/) { @license_pid = $1; } if ($data_line =~ /Total of (\d+) licenses issued/) { $max_licenses = $1; } elsif ($data_line =~ /Total of (\d+) licenses in use/) { $licenses_used = $1; } elsif ($data_line =~ /minutes \(at /) { ($JUNK, $user, $JUNK) = split (/\s+/, $data_line); $user_list ="$user,$user_list"; }

    and here is the line that is giving me trouble. I've tried loading the data into an array (string shown here), but it's not working. I would prefer to put it in an array (more further down)

    elsif ($data_line =~ /\, start /) { $data_line =~ s/^\s+//g; print $data_line; ($user, $IP, $machine, $VER, $JUNK, $PID, $JUNK, $SDAY, $SDATE +, $start_time) = split (/\ /, $data_line); $user_list ="$user,$user_list"; $start_list ="$start_time,$start_list"; $licenses_used++; } } close LICENSES;

    Here's a snippet of the output $flexlm_cmd command output:

    user1 192.168.1.1 machine1 (v1.1) (flexlmserver/27000 1009), start Sat + 3/30 12:53 user2 192.168.1.2 machine2 (v1.1) (flexlmserver/27000 123), start Sat +3/30 2:45

    The code above works fine but not on multiple lines. The variables only end up with the values from the last line (I tried using arrays instead and that didn't work either). My objective is to build arrays where I have paired up the user name (first block of characters in the line), the process ID (the sixth block of characters, and I have to trim the ")"), and the time (the last block of characters). So from the above example, the output of the arrays would be:

    array1 = (user1,1009,12:53) array2 = (user2,123,2:45)

    I need an association between the PID and the time, so I can sort them by time, then perform further processing on the PIDs that are the oldest. That should be easy, but I can't seem to load up the arrays as shown above (if that is indeed the best way to do this). Again, my apologies for the simple question. I am under time pressure to get this done and all the tutorials I have read on arrays, regex and splitting have not all added together for a solution, so I thought I'd seek the wisdom of the monks. Thank you.

      I think your problem is that you're not actually creating an array. Consider:

      use strict; use warnings; my @parsed; # <- Here's the array in question while ( <DATA> ) { my @wanted = ( split )[ 0, 5, 9 ]; $wanted[1] =~ s/\D//g; push @parsed, join ',', @wanted; } print "$_\n" for @parsed; __DATA__ user1 192.168.1.1 machine1 (v1.1) (flexlmserver/27000 1009), start Sat + 3/30 12:53 user2 192.168.1.2 machine2 (v1.1) (flexlmserver/27000 123), start Sat +3/30 2:45

      This gives an output that seems to correspond to what you request (but whether such a datastructure is ideal depends on how you intend to subsequently use it...).

        Thanks for the quick reply. Your code works as you described and as I requested, but I don't think I explained what I needed very well. Your code creates each series as an element in the array (each line of data is an element), but I need to be able to separate out the PID data in order to work with it. I need the user to log what user was involved, and I need the time to be able to sort the list and choose the 10 "oldest" PIDS for the day. To illustrate, here's the same data:

        user1 192.168.1.1 machine1 (v1.1) (flexlmserver/27000 1009), start Sat + 3/30 12:53 user2 192.168.1.2 machine2 (v1.1) (flexlmserver/27000 123), start Sat +3/30 2:45

        With your code gives me the output:

        $parsed[0] = user1,1009,12:53 $parsed[1] = user2,123,2:45

        When I need something like:

        @row1 = (user1,1009,12:53) $row1[0] = user1 $row1[1] = 1009 $row1[2] = 12:53 @row2 = (user2,123,2:45) $row2[0] = user2 $row2[1] = 123 $row2[2] = 2:45

        So perhaps what I really need is a multidimensional array or a way to split up the file into a grid? My end goal is to take the oldest PIDs so I can run a command on those PID numbers. Therefore I need to associate the time with the PIDs so I can identify the ones I need. You are correct the I am not asking for the correct data construct. Any further suggestions would be greatly appreciated.

      Just a comment on your code, not exactly related to what you've asked, but here goes anyway, as I was just reading about this last night. You have these two lines.

      ($JUNK, $user, $JUNK) = split (/\s+/, $data_line); ... ($user, $IP, $machine, $VER, $JUNK, $PID, $JUNK, $SDAY, $SDATE, $start +_time) = split (/\ /, $data_line);
      When assigning to a list, you can assign to undef to throw away a value, thereby not creating a useless variable.
      (undef, $user, undef) = split (/\s+/, $data_line); ... ($user, $IP, $machine, $VER, undef, $PID, undef, $SDAY, $SDATE, $start +_time) = split (/\ /, $data_line);
      This is explained in perldata, under 'List value constructors'. It also gets rid of the need to declare $JUNK if you enable strict 'vars', which you probably should consider if you haven't already done so.

        Thanks, Farang. I inherited this code from someone else and I thought there might be a better way to do that. I appreciate the tip!