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

bartrad has asked for the wisdom of the Perl Monks concerning the following question:

Hi all, looking for some help please? I have an output that lists some utilization stats (~0.00). These stats are appear twice (in/out) and are repeated three times per time round the for loop. I'm struggling with figuring out how to store these for each $lag_traffic and then pass them to a hash to store referencing which $lag_traffic they belong to for then onward evaluation later.

What I've got so far pulls out 6 ~0.00's and printing out %lag_load shows there's 6 values against each $lag_traffic, but not the actual values.
Totals 1144 12 1116 12 0 0 % Util ~0.00 -- ~0.00 -- -- - +- Totals 1720 18 1529 16 0 0 % Util ~0.00 -- ~0.00 -- -- - +- Totals 1539 16 1425 16 0 0 % Util ~0.00 -- ~0.00 -- -- - +-
foreach $lag_traffic (@lag_id) { my $text = $host->cmd("monitor lag $lag_traffic interval 3 repeat +3 rate | match Totals post-lines 1"); @lag_util = ( $text =~ m/(.\d+\.\d+)/g ); $lag_load{$lag_traffic} = @lag_util; }
$VAR1 = [ '~0.00', '~0.00', '~0.00', '~0.00', '~0.00', '~0.00' ]; $VAR1 = { '200' => 6, '199' => 6 };

Replies are listed 'Best First'.
Re: Store and print multiple strings
by roboticus (Chancellor) on Mar 12, 2018 at 13:33 UTC

    bartrad:

    I'm having a bit of difficulty figuring out what you're asking, but if I understand correctly, you expect the second part of your output to look like:

    $VAR1 = { '200' => [ '~0.00', '~0.00', '~0.00', '~0.00', '~0.00', '~0.00' ], '199' => [ '~0.00', '~0.00', '~0.00', '~0.00', '~0.00', '~0.00' ], };

    If I've guessed correctly, then the problem is that you're assigning an array to a scalar in this line:

    $lag_load{$lag_traffic} = @lag_util;

    and the way to fix it is to create an array reference, and put that into the hash like this:

    $lag_load{$lag_traffic} = [ @lag_util ];

    You might consider tuning up your question a bit, in order to make it more accurate, and easier to see what you're asking. Your code doesn't show how you're printing your values out, and it doesn't look like it could possibly give you the results you've shown because the match expression doesn't capture the tilde character (~). You didn't show what you expected to see, either, so I'm reduced to making a guess.

    Update: Struck out incorrect statement, as AnomalousMonk pointed out that the regex actually does capture the tilde (because I didn't read the regex carefully enough, I overlooked the '.').

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      ... the match expression doesn't capture the tilde character (~).

      In general, I'm having difficulty figuring out the OP too, but I think the tilde will be captured by the first  . (dot) in the  .\d+\.\d+ expression.

      Update: Since my guess is that the  ~ (tilde) character seems always to be present in  .\d+\.\d+ (e.g., ~0.00) groups, my inclination would be to specify it explicitly in the match expression:  ~\d+\.\d+


      Give a man a fish:  <%-{-{-{-<

      Hi, I'm capturing the string using (.\d+\.\d+) with the . matching the ~ since that is only present if the values are 0.00. If they were 51.11 for example, there would be no ~ but would still match as there's spaces after Util before the actual digit. Might be a better way to do that?

      My values are just printed to screen and are held in $text:

      my $text = $host->cmd("monitor lag $lag_traffic interval 3 repeat 3 ra +te | match Totals post-lines 1");

      $lag_traffic is just derived from another input that is held in @lag_id:

      my $lags = $host->cmd("show lag description"); my @lag_id = ( $lags =~ m/(\d+)\Se\S/g );

      For a guess, you're pretty spot on. Essentially what I want is to have the following displayed:

      LAG ID 200:
      1 - Input - x Output - x
      2 - Input - x Output - x
      3 - Input - x Output - x
      LAG ID 199:
      1 - Input - x Output - x
      2 - Input - x Output - x
      3 - Input - x Output - x

      Your recommendation solves why it was just counting the contents, so thank you. Given I know the first value in the text is always input and the second is always output, would it be easier to split them up before or after putting them in the key?

        ... the ~ ... is only present if the values are 0.00.

        Since you seem to want to capture only a  ~ (tilde), if present, and no other character (including, in one case, a  - (negative sign) in the example below), I would use:

        c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my $text = 'foo ~0.00 bar 1.0 fee 0.2 baz 0.03 boff -0.09 zot 10.09'; my @lag_util = $text =~ m{ ~? \d+ [.] \d+ }xmsg; dd \@lag_util; " ["~0.00", "1.0", "0.2", "0.03", "0.09", "10.09"]


        Give a man a fish:  <%-{-{-{-<

        bartrad:

        Sorry about that, I didn't read your code carefully enough, and managed to overlook the initial '.' in your regex, and managed to flub my initial response.

        If you're always getting six values and you want to format them as you describe, I don't really see any reason to prefer splitting them up before putting them in the hash versus splitting them up afterwards when you're printing your report.

        Generally, I try to let the problem I'm solving guide my choices on building the data structure. If you're doing further processing between the "acquire the data" step and the "report the data" step, then that further processing might be simpler if the data were stored one way vs. storing it the other way. If you don't have an intermediate step yet, but suspect you may in the future, then you might want to put the data in a format suitable for the expected processing if it's no more difficult one way or the other. If there's any extra effort required to put the data in that form and you're not sure you'll use the script again, then you might just put a nice comment in the form of:

        # TODO: if we need to jibber the frobnitz, we might want to reform +at the data like # $lag_load{$lag_traffic} = [ [ $inVal1, $outVal1 ], ... ]; # or # $lag_load{$lag_traffic} = [ { in=>$inVal1, out=>$outVal1 }, ... +]; # be sure to update the zig_zag_report subroutine accordingly!

        to prompt the future you, if/when the need arises. That way, you don't have to spend the effort unless necessary. Since it's just a comment to give you a little context when you revisit the code, it need not be syntactically perfect--you're just wanting to pass on some ideas to your future self while the code is fresh in your mind.

        ...roboticus

        When your only tool is a hammer, all problems look like your thumb.

      ... and "auto-vivification" in Perl might make it even more straightforward to do that.

        anonymous monk:

        I can't quite tell what you mean. Care to explain a bit?

        ...roboticus

        When your only tool is a hammer, all problems look like your thumb.